diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cea058af9..d101b480d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -638,8 +638,8 @@ add_definitions(-DOPNMIDI_USE_LEGACY_EMULATOR) add_definitions(-DADLMIDI_DISABLE_MUS_SUPPORT -DADLMIDI_DISABLE_XMI_SUPPORT -DADLMIDI_DISABLE_MIDI_SEQUENCER) add_definitions(-DOPNMIDI_DISABLE_MUS_SUPPORT -DOPNMIDI_DISABLE_XMI_SUPPORT -DOPNMIDI_DISABLE_MIDI_SEQUENCER) -# Disable ADLMIDI's MIDI Sequencer, MUS and XMI converters -add_definitions(-DADLMIDI_DISABLE_MUS_SUPPORT -DADLMIDI_DISABLE_XMI_SUPPORT -DADLMIDI_DISABLE_MIDI_SEQUENCER) +# Disable OPNMIDI's experimental yet emulator (using of it has some issues and missing notes in playback) +add_definitions(-DOPNMIDI_DISABLE_GX_EMULATOR) # Project files should be aware of the header files. We can GLOB these since # there's generally a new cpp for every header so this file will get changed @@ -855,14 +855,25 @@ set( FASTMATH_SOURCES sound/adlmidi/adlmidi_midiplay.cpp sound/adlmidi/adlmidi_opl3.cpp sound/adlmidi/adlmidi_private.cpp - sound/adlmidi/dbopl.cpp - sound/adlmidi/nukedopl3.c + sound/adlmidi/chips/dosbox/dbopl.cpp + sound/adlmidi/chips/dosbox_opl3.cpp + sound/adlmidi/chips/nuked/nukedopl3_174.c + sound/adlmidi/chips/nuked/nukedopl3.c + sound/adlmidi/chips/nuked_opl3.cpp + sound/adlmidi/chips/nuked_opl3_v174.cpp + sound/adlmidi/wopl/wopl_file.c + sound/opnmidi/chips/gens_opn2.cpp + sound/opnmidi/chips/gens/Ym2612_Emu.cpp + sound/opnmidi/chips/mame/mame_ym2612fm.c + sound/opnmidi/chips/mame_opn2.cpp + sound/opnmidi/chips/nuked_opn2.cpp + sound/opnmidi/chips/nuked/ym3438.c sound/opnmidi/opnmidi.cpp sound/opnmidi/opnmidi_load.cpp sound/opnmidi/opnmidi_midiplay.cpp sound/opnmidi/opnmidi_opn2.cpp sound/opnmidi/opnmidi_private.cpp - sound/opnmidi/Ym2612_ChipEmu.cpp + ) set (PCH_SOURCES diff --git a/src/sound/adlmidi/adldata.cpp b/src/sound/adlmidi/adldata.cpp index 1556f4d9c..7215d7c89 100644 --- a/src/sound/adlmidi/adldata.cpp +++ b/src/sound/adlmidi/adldata.cpp @@ -4,7 +4,7 @@ * FROM A NUMBER OF SOURCES, MOSTLY PC GAMES. * PREPROCESSED, CONVERTED, AND POSTPROCESSED OFF-SCREEN. */ -const adldata adl[4423] = +const adldata adl[4537] = { // ,---------+-------- Wave select settings // | ,-------ч-+------ Sustain/release rates // | | ,-----ч-ч-+---- Attack/decay rates @@ -4172,10 +4172,10 @@ const adldata adl[4423] = { 0x332ED12,0x1E7D211, 0x80,0x45, 0x2, +0 }, { 0x0F4E431,0x0F5F331, 0x97,0x86, 0x8, +0 }, { 0x3F0F701,0x1F8F900, 0x00,0x0D, 0xE, +0 }, - { 0x0F78111,0x3F7F054, 0x40,0x45, 0x8, +0 }, - { 0x0F78140,0x3F7F040, 0x40,0x01, 0xC, +14 }, - { 0x0F78111,0x2F7F054, 0x40,0x45, 0xA, +0 }, - { 0x0F78140,0x3F7F040, 0x40,0x05, 0xC, +14 }, + { 0x0F77111,0x3F7F011, 0x48,0x87, 0xA, +0 }, + { 0x0F78140,0x3F7F040, 0x86,0x00, 0xC, +14 }, + { 0x0F78140,0x3F7F040, 0x07,0x40, 0xC, +12 }, + { 0x0F78100,0x3F7F000, 0x86,0x03, 0xC, +14 }, { 0x6F78AE8,0x649B1F4, 0x03,0x0A, 0xA, +0 }, { 0x6F78AE8,0x649B1F4, 0x43,0x4B, 0xA, +0 }, { 0x0609533,0x4E5C131, 0x63,0x05, 0x0, +0 }, @@ -4205,34 +4205,34 @@ const adldata adl[4423] = { 0x2C79613,0x4E45411, 0xD7,0x08, 0xA, +0 }, { 0x023E133,0x0F2F131, 0xA2,0x09, 0xE, +0 }, { 0x023F132,0x0F2F131, 0x24,0x0A, 0xE, +0 }, - { 0x5C3C404,0x1B4B519, 0xA1,0x00, 0xC, -31 }, - { 0x17A9913,0x0B4F213, 0x0F,0x00, 0x8, -19 }, - { 0x223F832,0x4055421, 0x99,0x8A, 0xC, +0 }, + { 0x4C3C404,0x4B4B519, 0x21,0x05, 0x0, -31 }, + { 0x17A9913,0x0B4F213, 0x0F,0x00, 0x0, -19 }, + { 0x223F832,0x4056421, 0x99,0x8A, 0xC, +0 }, { 0x433CB32,0x5057561, 0x9B,0x8A, 0xA, +0 }, { 0x1029033,0x4044561, 0x5B,0x85, 0x4, +0 }, { 0x4109033,0x2044520, 0xA8,0x85, 0xA, +0 }, - { 0x2034170,0x0043671, 0x08,0x20, 0x9, +0 }, - { 0x1022171,0x0042671, 0x0C,0x17, 0xB, +0 }, - { 0x0055021,0x0F55022, 0x1C,0x0F, 0x7, +0 }, - { 0x0F54066,0x0F55024, 0x5A,0x0F, 0x7, -12 }, + { 0x2034170,0x0043671, 0x0B,0x20, 0xB, +0 }, + { 0x1024171,0x0043671, 0x0C,0x17, 0xB, +0 }, + { 0x005A061,0x0F55022, 0x69,0x06, 0x0, +0 }, + { 0x0008060,0x0F55021, 0x33,0x08, 0x0, +12 }, { 0x239B420,0x0076121, 0x50,0x05, 0x6, +0 }, { 0x139B462,0x00D7161, 0x91,0x14, 0x0, +0 }, - { 0x05470F1,0x07460B1, 0x5A,0x80, 0x0, +0 }, - { 0x054A0F1,0x07460B1, 0x5E,0x80, 0x0, +0 }, - { 0x2436110,0x114D211, 0x90,0x00, 0xC, +0 }, - { 0x1436192,0x145F312, 0x8F,0x00, 0xC, +0 }, + { 0x05470F1,0x07440B1, 0x69,0x80, 0x0, +0 }, + { 0x054A0F1,0x07430B1, 0x5E,0x80, 0x0, +0 }, + { 0x2436110,0x714D211, 0xCD,0x00, 0xA, +0 }, + { 0x5436192,0x745F312, 0xCB,0x00, 0xA, +0 }, { 0x0147421,0x0077521, 0x94,0x04, 0xE, +0 }, { 0x0178461,0x008AF28, 0x10,0xA6, 0xC, +0 }, { 0x0235271,0x0198161, 0x1E,0x08, 0xE, +0 }, { 0x0235361,0x0196161, 0x1D,0x03, 0xE, +0 }, { 0x0155331,0x0378261, 0x94,0x00, 0xA, +0 }, { 0x118543A,0x5177472, 0x1E,0x00, 0x4, -12 }, - { 0x0364121,0x02B7221, 0x21,0x08, 0xC, +0 }, - { 0x026F021,0x0056121, 0x26,0x03, 0xC, +0 }, + { 0x0365121,0x0257221, 0x1E,0x08, 0x0, +0 }, + { 0x2844521,0x20592A0, 0x23,0x03, 0x0, +0 }, { 0x0578321,0x117C021, 0x19,0x03, 0xC, +0 }, { 0x2E77530,0x307F520, 0x10,0x08, 0x8, +0 }, - { 0x036F121,0x337F121, 0x92,0x08, 0xE, +0 }, - { 0x0368121,0x037F121, 0x92,0x08, 0xE, +0 }, + { 0x036F121,0x337F121, 0x95,0x08, 0xE, +0 }, + { 0x0368121,0x037F121, 0x95,0x08, 0xE, +0 }, { 0x0A66121,0x0976121, 0x9B,0x08, 0xE, +0 }, { 0x5237731,0x1F65012, 0x4B,0x00, 0xA, +0 }, { 0x0137732,0x0F65011, 0xC7,0x0A, 0xA, +0 }, @@ -4241,11 +4241,11 @@ const adldata adl[4423] = { 0x10B8020,0x11B6330, 0x87,0x00, 0x8, +12 }, { 0x1235031,0x0077C24, 0xC0,0x08, 0x2, +0 }, { 0x045D933,0x4076C35, 0xD0,0x26, 0x4, +0 }, - { 0x2077830,0x2076331, 0x9F,0x00, 0xA, +0 }, + { 0x6077831,0x2076331, 0x1E,0x00, 0x6, +0 }, { 0x0199031,0x01B6134, 0x95,0x80, 0xA, +0 }, { 0x0177532,0x0174531, 0x93,0x03, 0xC, +0 }, { 0x0277530,0x0174536, 0x14,0x9C, 0xE, +12 }, - { 0x08D6EF1,0x02A3571, 0xC0,0x00, 0xE, +0 }, + { 0x08B8EF1,0x0285571, 0xC0,0x00, 0xE, +0 }, { 0x08860A1,0x01A6561, 0x5C,0x00, 0x8, +0 }, { 0x2176522,0x0277421, 0x5A,0x00, 0x6, +0 }, { 0x1267532,0x0166531, 0x8D,0x05, 0x4, +0 }, @@ -4267,12 +4267,12 @@ const adldata adl[4423] = { 0x32B7420,0x12BF134, 0x46,0x00, 0x8, +0 }, { 0x5029072,0x0069061, 0x96,0x0C, 0x8, +0 }, { 0x1019031,0x0069061, 0x1A,0x0C, 0x6, +0 }, - { 0x245C224,0x2550133, 0x81,0x80, 0xB, -36 }, - { 0x2459224,0x2556133, 0x81,0x80, 0xB, -36 }, + { 0x245C224,0x2550133, 0x81,0x80, 0x9, -36 }, + { 0x2459224,0x2556133, 0x81,0x80, 0x9, -36 }, { 0x132ED10,0x3E7D010, 0x87,0x0D, 0x6, +12 }, { 0x132ED30,0x3E7D010, 0x87,0x12, 0x6, +12 }, - { 0x033513A,0x013C121, 0xA4,0x06, 0x2, +0 }, - { 0x273F325,0x0228231, 0x20,0x06, 0x4, +0 }, + { 0x073513A,0x013C121, 0xA4,0x0A, 0x2, +0 }, + { 0x273F325,0x0228231, 0x20,0x0A, 0x4, +0 }, { 0x0031131,0x0054361, 0xD4,0x08, 0x4, +0 }, { 0x20311B0,0x00543E1, 0xD9,0x08, 0x4, +0 }, { 0x245A121,0x126A121, 0x98,0x05, 0xC, +0 }, @@ -4300,8 +4300,8 @@ const adldata adl[4423] = { 0x5522363,0x0131331, 0x1A,0x8D, 0x7, +0 }, { 0x0B67061,0x0928032, 0x9C,0x11, 0xA, +0 }, { 0x0057F21,0x0038F62, 0x9C,0x11, 0xA, +0 }, - { 0x0025511,0x1748201, 0x94,0x06, 0xE, +0 }, - { 0x2045501,0x2445501, 0x15,0x0D, 0xA, +0 }, + { 0x0625331,0x1648221, 0x94,0x06, 0xE, +0 }, + { 0x2645321,0x2445521, 0x15,0x0D, 0xA, +0 }, { 0x0B37121,0x5F48221, 0x16,0x08, 0x2, +0 }, { 0x2B37102,0x5F48221, 0x90,0x08, 0x6, +0 }, { 0x1127533,0x4F4F211, 0x58,0x03, 0x6, +0 }, @@ -4355,24 +4355,36 @@ const adldata adl[4423] = { 0x048FA00,0x008F900, 0x00,0x00, 0x6, +12 }, { 0x287F702,0x678F802, 0x80,0x88, 0xE, +12 }, { 0x2F7F602,0x0F8F802, 0x00,0x88, 0xE, +12 }, + { 0x008F700,0x007F609, 0x00,0x00, 0xD, -24 }, + { 0x0F1F105,0x0078407, 0x00,0x08, 0xC, -12 }, { 0x05476C1,0x30892C5, 0x80,0x08, 0x0, +0 }, { 0x05477C1,0x30892C5, 0x00,0x08, 0xA, -2 }, - { 0x005C604,0x005C604, 0x08,0x00, 0x1, +0 }, - { 0x509F902,0x057AB07, 0x03,0x07, 0xC, +12 }, - { 0x254F307,0x307F905, 0x04,0x08, 0x6, -5 }, - { 0x254F307,0x207F905, 0x04,0x08, 0x8, +0 }, - { 0x509F912,0x057AB07, 0x03,0x07, 0xC, +12 }, + { 0x007C604,0x007C604, 0x08,0x08, 0x1, +0 }, + { 0x201F302,0x057AB09, 0x03,0x07, 0xC, +12 }, + { 0x058F30B,0x308F90D, 0x04,0x08, 0x6, +0 }, + { 0x255F308,0x308F909, 0x04,0x08, 0x8, +4 }, + { 0x006C604,0x007C604, 0x08,0x08, 0x1, +0 }, + { 0x201F312,0x057AB09, 0x03,0x07, 0xC, +12 }, { 0x254D307,0x3288905, 0x04,0x03, 0xA, -5 }, - { 0x509F902,0x057AB07, 0x03,0x07, 0x0, +12 }, - { 0x210F509,0x605FE05, 0x8A,0x8A, 0xE, +12 }, - { 0x400F509,0x605FE05, 0x07,0x8A, 0xA, +12 }, + { 0x0015500,0x007C716, 0x0C,0x00, 0x0, +0 }, + { 0x201F312,0x057AB09, 0x00,0x07, 0xC, +12 }, + { 0x0015500,0x007C718, 0x0C,0x00, 0x0, +0 }, + { 0x001F312,0x047BB05, 0x03,0x07, 0xC, +12 }, + { 0x0015500,0x007C71B, 0x0C,0x00, 0x0, +0 }, + { 0x201F312,0x047BB09, 0x03,0x07, 0xC, +12 }, + { 0x291F108,0x333F401, 0x00,0x00, 0x8, +12 }, + { 0x291F108,0x333F501, 0x00,0x00, 0x8, +12 }, + { 0x0015500,0x007C71F, 0x0C,0x00, 0x0, +0 }, + { 0x300F50C,0x605FE05, 0x07,0x8A, 0x0, +12 }, + { 0x310F508,0x604FE05, 0x86,0x8A, 0x0, +11 }, { 0x2E1F11E,0x3F3F318, 0x04,0x00, 0x8, +0 }, { 0x2777603,0x3679601, 0x87,0x08, 0x6, +12 }, { 0x277C643,0x3679601, 0x87,0x08, 0xE, +12 }, { 0x366F905,0x099F701, 0x00,0x00, 0xC, +12 }, + { 0x291F108,0x334F401, 0x00,0x00, 0x8, +12 }, { 0x431A000,0x085B41A, 0x81,0x05, 0xA, +12 }, { 0x459F640,0x185B418, 0x00,0x20, 0xB, +12 }, - { 0x212FD08,0x305FD03, 0x01,0x03, 0x8, +12 }, + { 0x300F50C,0x605FE04, 0x07,0x8A, 0x0, +12 }, { 0x2A8F9E3,0x0779643, 0x1E,0x08, 0x2, +6 }, { 0x0A5F7E8,0x0D89949, 0xDE,0x00, 0x0, +0 }, { 0x2A8F9E3,0x0779643, 0x1E,0x00, 0xE, +12 }, @@ -4439,4568 +4451,4925 @@ const adldata adl[4423] = { 0x023F331,0x09C4333, 0x45,0x25, 0x6, -12 }, { 0x04CA700,0x04FC600, 0x00,0x2B, 0x0, -12 }, { 0x0B5F704,0x002010C, 0x00,0x00, 0x8, +21 }, + { 0x050F113,0x076D201, 0x50,0x40, 0x6, +0 }, + { 0x050F113,0x076D201, 0x50,0x00, 0x6, +0 }, + { 0x054F113,0x076D201, 0x53,0x00, 0x6, +0 }, + { 0x054F113,0x076D201, 0x50,0x00, 0x6, +0 }, + { 0x0FFF92C,0x0FFC1A1, 0xD4,0x00, 0x0, +0 }, + { 0x050F101,0x07CD301, 0x4F,0x00, 0x6, +0 }, + { 0x030A131,0x074C216, 0x81,0x80, 0x8, +0 }, + { 0x0FFF201,0x0F8F101, 0x11,0x00, 0xA, +0 }, + { 0x011FAD6,0x0FCF161, 0x4D,0x00, 0x8, +0 }, + { 0x011FA16,0x0F1F1E1, 0x4D,0x00, 0x8, +0 }, + { 0x011FAD6,0x0F5F561, 0x4D,0x00, 0x8, +0 }, + { 0x015DA45,0x0F6F361, 0x4E,0x80, 0x0, +0 }, + { 0x0F0FE04,0x0B5F6C2, 0x00,0x00, 0xE, -12 }, + { 0x004FE11,0x0BDF211, 0x11,0x00, 0x8, +0 }, + { 0x00FFF24,0x00FFF21, 0x80,0x80, 0x1, -12 }, + { 0x0FFF92C,0x0FFC0A1, 0xD4,0x00, 0x0, -12 }, + { 0x0E5F8E2,0x00EC0E1, 0xCA,0x00, 0x8, +0 }, + { 0x0FD5524,0x02D5031, 0x54,0x00, 0xE, +0 }, + { 0x0C8F253,0x0C5F211, 0x16,0x40, 0x4, +0 }, + { 0x0C8F253,0x0C5F211, 0x20,0x00, 0x4, +0 }, + { 0x0FFF111,0x3FFF054, 0x43,0x00, 0x8, +0 }, + { 0x0FFF111,0x3FFF054, 0x43,0x40, 0x8, +0 }, + { 0x0F0F0CA,0x06859EC, 0x4E,0x00, 0xC, +0 }, + { 0x02CD321,0x02CC321, 0x15,0x80, 0xA, +0 }, + { 0x0F2D401,0x08AC421, 0x18,0x80, 0xA, +0 }, + { 0x07AB400,0x07CC301, 0x1D,0x00, 0x0, +12 }, + { 0x07E7330,0x09E8021, 0x16,0x00, 0xE, +12 }, + { 0x004FE11,0x0BDF211, 0x0A,0x00, 0x8, +0 }, + { 0x0035171,0x0175461, 0x20,0x00, 0xE, +0 }, + { 0x0035171,0x0175461, 0x1E,0x00, 0xE, +0 }, + { 0x0035171,0x0175423, 0x1C,0x00, 0xE, +0 }, + { 0x04CA800,0x04FD600, 0x0B,0x00, 0x0, +12 }, + { 0x075F502,0x0F3F201, 0x29,0x80, 0x0, +0 }, + { 0x0530900,0x094F702, 0x40,0x00, 0xE, -12 }, + { 0x01432F1,0x016F1E1, 0x18,0x00, 0x0, +0 }, + { 0x01432F1,0x01631E1, 0x18,0x00, 0x0, +0 }, + { 0x01132F1,0x014F1E1, 0x18,0x00, 0x0, +0 }, + { 0x0154011,0x03831F1, 0x92,0x00, 0x8, +0 }, + { 0x0948411,0x0F4F4E4, 0x03,0x40, 0x8, -12 }, + { 0x0577361,0x017A021, 0x19,0x00, 0xC, +0 }, + { 0x0585361,0x018A021, 0x19,0x00, 0xC, +0 }, + { 0x0565361,0x016A021, 0x19,0x00, 0xC, +0 }, + { 0x0035171,0x0675421, 0x1C,0x00, 0xE, +0 }, + { 0x0576361,0x017A021, 0x1C,0x00, 0xC, +0 }, + { 0x0176E70,0x00E6B22, 0x8D,0x00, 0x2, +12 }, + { 0x00E7170,0x00E7823, 0x16,0x07, 0xE, +12 }, + { 0x0178731,0x00E8B22, 0x45,0x00, 0x2, +0 }, + { 0x0195132,0x0396061, 0x9A,0x80, 0xC, +0 }, + { 0x02495A2,0x02A60E2, 0x1D,0x80, 0x2, -12 }, + { 0x0AFD6A1,0x02A60E2, 0x13,0x80, 0x2, +0 }, + { 0x02498A2,0x02A60E2, 0x1D,0x80, 0x2, -12 }, + { 0x04FD6A1,0x02A60E2, 0x13,0x80, 0x2, +0 }, + { 0x0BF7721,0x02A60A1, 0x19,0x80, 0x6, +0 }, + { 0x0E5F8E2,0x00E70E1, 0xCA,0x00, 0x8, +0 }, + { 0x30FF221,0x018F221, 0x1D,0x00, 0x0, +0 }, + { 0x0FFF041,0x0FFF001, 0x11,0x00, 0xA, +0 }, + { 0x0BDF101,0x39FF102, 0xCE,0x80, 0x0, +0 }, + { 0x0FFF141,0x0FFF001, 0x0E,0x09, 0xA, +0 }, + { 0x0867261,0x01450E1, 0xA7,0x80, 0x2, +0 }, + { 0x049F430,0x033F410, 0x90,0x00, 0xC, +12 }, + { 0x0F0F0CA,0x06459CC, 0x4E,0x00, 0xC, +0 }, + { 0x0152011,0x0F831F1, 0x43,0x00, 0x8, +0 }, + { 0x0152011,0x0F831F1, 0x92,0x00, 0x8, +0 }, + { 0x010FF34,0x004FF03, 0x91,0x00, 0xA, +0 }, + { 0x002A4B0,0x04240D7, 0x84,0x80, 0x0, +0 }, + { 0x032B6B3,0x031D1B0, 0x4A,0x00, 0xE, +12 }, + { 0x0978211,0x0F3F0E4, 0x03,0x40, 0x8, +0 }, + { 0x002A4B4,0x04240D7, 0x87,0x80, 0x6, +0 }, + { 0x0F0A133,0x0F37115, 0x85,0x80, 0x8, +0 }, + { 0x053F101,0x074F211, 0x4F,0x00, 0x6, +0 }, + { 0x0E8F80B,0x0F4C301, 0xCA,0x00, 0x0, +0 }, + { 0x0FFF001,0x0F8F001, 0x11,0x00, 0xA, +0 }, + { 0x0EE7130,0x01E8823, 0x16,0x00, 0xE, +0 }, + { 0x025DA09,0x015F101, 0x4E,0x00, 0xA, +0 }, + { 0x0FFF832,0x07FF511, 0x44,0x00, 0xE, +12 }, + { 0x0F33900,0x005FF00, 0x3F,0x00, 0x0, +12 }, + { 0x0FFF832,0x0F8F501, 0x44,0x00, 0xE, +0 }, + { 0x0F0F007,0x0DC5C00, 0x00,0x00, 0xE, +12 }, + { 0x002A4B0,0x04240D7, 0xC4,0x89, 0x0, +0 }, + { 0x1111EF0,0x11121E2, 0x00,0xC0, 0x8, -12 }, + { 0x0EFE800,0x0FFA500, 0x0D,0x00, 0x6, +12 }, + { 0x077F005,0x0EDFA00, 0x00,0x00, 0xE, +12 }, + { 0x0F0F006,0x0F7F700, 0x00,0x00, 0xE, +12 }, + { 0x1FFF005,0x0B9F800, 0x00,0x00, 0xE, +0 }, + { 0x0F33900,0x005FF00, 0x3F,0x00, 0x0, +0 }, + { 0x077F005,0x0FBFA00, 0x00,0x00, 0xE, +0 }, + { 0x077F005,0x0EAFA00, 0x00,0x00, 0xE, +12 }, + { 0x0FFF005,0x0FFF600, 0x00,0x06, 0xE, +0 }, + { 0x0C0F006,0x034C6CF, 0x0E,0x00, 0xE, +0 }, + { 0x360F207,0x352F212, 0x0A,0x0C, 0x0, +0 }, + { 0x360F207,0x352F212, 0x0A,0x0B, 0x0, +0 }, + { 0x0F0F406,0x0F78700, 0x00,0x0D, 0xE, +0 }, + { 0x1FFF005,0x0B9F800, 0x00,0x00, 0x8, +0 }, + { 0x0F0F000,0x0F5F500, 0x00,0x09, 0xA, +0 }, + { 0x0590900,0x097F700, 0x40,0x00, 0x0, +24 }, + { 0x052F301,0x194F700, 0x40,0x00, 0x0, +12 }, + { 0x0530907,0x096F605, 0x40,0x00, 0xE, +0 }, + { 0x070F005,0x0E57A00, 0x00,0x10, 0xE, +12 }, + { 0x070F005,0x0E59A00, 0x00,0x10, 0xE, +12 }, + { 0x070F005,0x0E55A00, 0x00,0x10, 0xE, +12 }, + { 0x07BF003,0x07BF502, 0x8A,0x80, 0x8, +0 }, + { 0x07BF003,0x07BF402, 0x8A,0x80, 0x8, +0 }, }; -const struct adlinsdata adlins[4549] = +const struct adlinsdata adlins[4804] = { - { 0, 0, 0, 0, 1660, 1660,0.000000 }, - { 1, 1, 0, 0, 1746, 1746,0.000000 }, - { 2, 2, 0, 0, 1980, 1980,0.000000 }, - { 3, 3, 0, 0, 1553, 1553,0.000000 }, - { 4, 4, 0, 0, 1233, 1233,0.000000 }, - { 5, 5, 0, 0, 1980, 1980,0.000000 }, - { 6, 6, 0, 0, 1100, 1100,0.000000 }, - { 7, 7, 0, 0, 1233, 1233,0.000000 }, - { 8, 8, 0, 0, 940, 940,0.000000 }, - { 9, 9, 0, 0, 1100, 1100,0.000000 }, - { 10, 10, 0, 0, 460, 460,0.000000 }, - { 11, 11, 0, 0, 1740, 1740,0.000000 }, - { 12, 12, 0, 0, 66, 66,0.000000 }, - { 13, 13, 0, 0, 140, 140,0.000000 }, - { 14, 14, 0, 0, 940, 940,0.000000 }, - { 15, 15, 0, 0, 266, 266,0.000000 }, - { 16, 16, 0, 0, 40000, 33,0.000000 }, - { 17, 17, 0, 0, 40000, 6,0.000000 }, - { 18, 18, 0, 0, 40000, 13,0.000000 }, - { 19, 19, 0, 0, 40000, 193,0.000000 }, - { 20, 20, 0, 0, 40000, 193,0.000000 }, - { 21, 21, 0, 0, 40000, 6,0.000000 }, - { 22, 22, 0, 0, 40000, 66,0.000000 }, - { 23, 23, 0, 0, 40000, 66,0.000000 }, - { 24, 24, 0, 0, 1026, 1026,0.000000 }, - { 25, 25, 0, 0, 1826, 1826,0.000000 }, - { 26, 26, 0, 0, 1813, 1813,0.000000 }, - { 27, 27, 0, 0, 1080, 1080,0.000000 }, - { 28, 28, 0, 0, 40000, 0,0.000000 }, - { 29, 29, 0, 0, 40000, 13,0.000000 }, - { 30, 30, 0, 0, 40000, 13,0.000000 }, - { 31, 31, 0, 0, 4200, 4200,0.000000 }, - { 32, 32, 0, 0, 940, 940,0.000000 }, - { 33, 33, 0, 0, 40000, 20,0.000000 }, - { 34, 34, 0, 0, 1746, 1746,0.000000 }, - { 35, 35, 0, 0, 40000, 0,0.000000 }, - { 36, 36, 0, 0, 2400, 2400,0.000000 }, - { 37, 37, 0, 0, 4166, 4166,0.000000 }, - { 38, 38, 0, 0, 1740, 1740,0.000000 }, - { 39, 39, 0, 0, 40000, 26,0.000000 }, - { 40, 40, 0, 0, 40000, 86,0.000000 }, - { 41, 41, 0, 0, 40000, 6,0.000000 }, - { 42, 42, 0, 0, 40000, 133,0.000000 }, - { 43, 43, 0, 0, 40000, 126,0.000000 }, - { 44, 44, 0, 0, 333, 333,0.000000 }, - { 45, 45, 0, 0, 940, 940,0.000000 }, - { 46, 46, 0, 0, 1046, 1046,0.000000 }, - { 47, 47, 0, 0, 40000, 33,0.000000 }, - { 48, 48, 0, 0, 1766, 13,0.000000 }, - { 49, 49, 0, 0, 40000, 220,0.000000 }, - { 50, 50, 0, 0, 40000, 153,0.000000 }, - { 51, 51, 0, 0, 40000, 146,0.000000 }, - { 52, 52, 0, 0, 2300, 2300,0.000000 }, - { 53, 53, 0, 0, 40000, 140,0.000000 }, - { 54, 54, 0, 0, 233, 233,0.000000 }, - { 55, 55, 0, 0, 40000, 6,0.000000 }, - { 56, 56, 0, 0, 40000, 6,0.000000 }, - { 57, 57, 0, 0, 40000, 6,0.000000 }, - { 58, 58, 0, 0, 40000, 6,0.000000 }, - { 59, 59, 0, 0, 40000, 6,0.000000 }, - { 60, 60, 0, 0, 40000, 0,0.000000 }, - { 61, 61, 0, 0, 40000, 26,0.000000 }, - { 62, 62, 0, 0, 40000, 0,0.000000 }, - { 63, 63, 0, 0, 40000, 6,0.000000 }, - { 64, 64, 0, 0, 40000, 20,0.000000 }, - { 65, 65, 0, 0, 40000, 20,0.000000 }, - { 66, 66, 0, 0, 40000, 0,0.000000 }, - { 67, 67, 0, 0, 40000, 6,0.000000 }, - { 68, 68, 0, 0, 3940, 3940,0.000000 }, - { 69, 69, 0, 0, 40000, 6,0.000000 }, - { 70, 70, 0, 0, 40000, 60,0.000000 }, - { 71, 71, 0, 0, 40000, 6,0.000000 }, - { 72, 72, 0, 0, 40000, 6,0.000000 }, - { 73, 73, 0, 0, 40000, 13,0.000000 }, - { 74, 74, 0, 0, 40000, 0,0.000000 }, - { 75, 75, 0, 0, 40000, 73,0.000000 }, - { 76, 76, 0, 0, 40000, 53,0.000000 }, - { 77, 77, 0, 0, 40000, 53,0.000000 }, - { 78, 78, 0, 0, 40000, 53,0.000000 }, - { 79, 79, 0, 0, 40000, 0,0.000000 }, - { 80, 80, 0, 0, 40000, 0,0.000000 }, - { 81, 81, 0, 0, 40000, 33,0.000000 }, - { 82, 82, 0, 0, 40000, 6,0.000000 }, - { 83, 83, 0, 0, 40000, 6,0.000000 }, - { 84, 84, 0, 0, 40000, 73,0.000000 }, - { 85, 85, 0, 0, 40000, 133,0.000000 }, - { 86, 86, 0, 0, 40000, 20,0.000000 }, - { 87, 87, 0, 0, 40000, 233,0.000000 }, - { 88, 88, 0, 0, 40000, 413,0.000000 }, - { 89, 89, 0, 0, 1660, 86,0.000000 }, - { 90, 90, 0, 0, 40000, 553,0.000000 }, - { 91, 91, 0, 0, 40000, 100,0.000000 }, - { 92, 92, 0, 0, 613, 13,0.000000 }, - { 93, 93, 0, 0, 40000, 126,0.000000 }, - { 94, 94, 0, 0, 40000, 53,0.000000 }, - { 95, 95, 0, 0, 993, 993,0.000000 }, - { 96, 96, 0, 0, 40000, 513,0.000000 }, - { 97, 97, 0, 0, 280, 280,0.000000 }, - { 98, 98, 0, 0, 40000, 73,0.000000 }, - { 99, 99, 0, 0, 2113, 2113,0.000000 }, - { 100, 100, 0, 0, 40000, 886,0.000000 }, - { 101, 101, 0, 0, 40000, 773,0.000000 }, - { 102, 102, 0, 0, 40000, 426,0.000000 }, - { 103, 103, 0, 0, 2413, 2413,0.000000 }, - { 104, 104, 0, 0, 1126, 1126,0.000000 }, - { 105, 105, 0, 0, 1046, 1046,0.000000 }, - { 106, 106, 0, 0, 866, 866,0.000000 }, - { 107, 107, 0, 0, 280, 280,0.000000 }, - { 108, 108, 0, 0, 40000, 6,0.000000 }, - { 109, 109, 0, 0, 40000, 113,0.000000 }, - { 110, 110, 0, 0, 40000, 6,0.000000 }, - { 111, 111, 0, 0, 1126, 1126,0.000000 }, - { 112, 112, 0, 0, 140, 140,0.000000 }, - { 113, 113, 0, 0, 246, 246,0.000000 }, - { 114, 114, 0, 0, 20, 20,0.000000 }, - { 115, 115, 0, 0, 146, 146,0.000000 }, - { 116, 116, 0, 0, 146, 146,0.000000 }, - { 117, 117, 0, 0, 340, 340,0.000000 }, - { 118, 118, 0, 0, 2280, 2280,0.000000 }, - { 119, 119, 0, 0, 286, 286,0.000000 }, - { 120, 120, 0, 0, 586, 586,0.000000 }, - { 121, 121, 0, 0, 4486, 4486,0.000000 }, - { 122, 122, 0, 0, 133, 133,0.000000 }, - { 123, 123, 0, 0, 186, 186,0.000000 }, - { 124, 124, 0, 0, 146, 146,0.000000 }, - { 125, 125, 0, 0, 40000, 113,0.000000 }, - { 126, 126, 0, 0, 140, 140,0.000000 }, - { 127, 127, 35, 0, 26, 26,0.000000 }, - { 128, 128, 52, 0, 20, 20,0.000000 }, - { 129, 129, 48, 0, 73, 73,0.000000 }, - { 130, 130, 58, 0, 40, 40,0.000000 }, - { 129, 129, 60, 0, 80, 80,0.000000 }, - { 131, 131, 47, 0, 106, 106,0.000000 }, - { 132, 132, 43, 0, 20, 20,0.000000 }, - { 131, 131, 49, 0, 146, 146,0.000000 }, - { 133, 133, 43, 0, 26, 26,0.000000 }, - { 131, 131, 51, 0, 160, 160,0.000000 }, - { 134, 134, 43, 0, 160, 160,0.000000 }, - { 131, 131, 54, 0, 140, 140,0.000000 }, - { 131, 131, 57, 0, 153, 153,0.000000 }, - { 135, 135, 72, 0, 600, 600,0.000000 }, - { 131, 131, 60, 0, 160, 160,0.000000 }, - { 136, 136, 76, 0, 513, 513,0.000000 }, - { 137, 137, 84, 0, 393, 393,0.000000 }, - { 138, 138, 36, 0, 400, 400,0.000000 }, - { 139, 139, 65, 0, 86, 86,0.000000 }, - { 140, 140, 84, 0, 406, 406,0.000000 }, - { 141, 141, 83, 0, 60, 60,0.000000 }, - { 135, 135, 84, 0, 406, 406,0.000000 }, - { 142, 142, 24, 0, 46, 46,0.000000 }, - { 136, 136, 77, 0, 500, 500,0.000000 }, - { 143, 143, 60, 0, 40, 40,0.000000 }, - { 144, 144, 65, 0, 40, 40,0.000000 }, - { 145, 145, 59, 0, 13, 13,0.000000 }, - { 146, 146, 51, 0, 46, 46,0.000000 }, - { 147, 147, 45, 0, 40, 40,0.000000 }, - { 148, 148, 71, 0, 140, 140,0.000000 }, - { 149, 149, 60, 0, 160, 160,0.000000 }, - { 150, 150, 58, 0, 153, 153,0.000000 }, - { 151, 151, 53, 0, 153, 153,0.000000 }, - { 152, 152, 64, 0, 86, 86,0.000000 }, - { 153, 153, 71, 0, 13, 13,0.000000 }, - { 154, 154, 61, 0, 313, 313,0.000000 }, - { 155, 155, 61, 0, 606, 606,0.000000 }, - { 156, 156, 44, 0, 80, 80,0.000000 }, - { 157, 157, 40, 0, 320, 320,0.000000 }, - { 158, 158, 69, 0, 20, 20,0.000000 }, - { 159, 159, 68, 0, 20, 20,0.000000 }, - { 160, 160, 63, 0, 33, 33,0.000000 }, - { 161, 161, 74, 0, 93, 93,0.000000 }, - { 162, 162, 60, 0, 353, 353,0.000000 }, - { 163, 163, 80, 0, 60, 60,0.000000 }, - { 164, 164, 64, 0, 873, 873,0.000000 }, - { 165, 165, 72, 0, 33, 33,0.000000 }, - { 166, 166, 73, 0, 286, 286,0.000000 }, - { 167, 167, 70, 0, 133, 133,0.000000 }, - { 168, 168, 68, 0, 20, 20,0.000000 }, - { 169, 169, 48, 0, 40, 40,0.000000 }, - { 131, 131, 53, 0, 126, 126,0.000000 }, - { 170, 170, 0, 0, 1020, 1020,0.000000 }, - { 171, 171, 0, 0, 40000, 0,0.000000 }, - { 172, 173, 0, 0, 1740, 1740,0.000000 }, - { 174, 175, 0, 0, 1260, 1260,0.000000 }, - { 176, 177, 0, 0, 1100, 1100,0.000000 }, - { 178, 178, 0, 0, 1100, 1100,0.000000 }, - { 179, 180, 0, 0, 726, 726,0.000000 }, - { 181, 181, 0, 0, 460, 460,0.000000 }, - { 182, 182, 0, 0, 246, 246,0.000000 }, - { 183, 184, 0, 0, 120, 120,0.000000 }, - { 185, 186, 0, 0, 840, 840,0.000000 }, - { 187, 187, 0, 0, 293, 293,0.000000 }, - { 188, 189, 0, 0, 1320, 1320,0.000000 }, - { 190, 191, 0, 0, 646, 6,0.000000 }, - { 192, 193, 0, 0, 40000, 6,0.000000 }, - { 194, 194, 0, 0, 40000, 6,0.000000 }, - { 195, 196, 0, 0, 40000, 0,0.000000 }, - { 197, 198, 0, 0, 40000, 20,0.000000 }, - { 199, 200, 0, 0, 2573, 6,0.000000 }, - { 201, 202, 0, 0, 953, 953,0.000000 }, - { 203, 204, 0, 0, 1740, 1740,0.000000 }, - { 205, 206, 0, 0, 1900, 1900,0.000000 }, - { 207, 208, 0, 0, 1986, 1986,0.000000 }, - { 209, 210, 0, 0, 760, 760,0.000000 }, - { 211, 212, 0, 0, 40000, 6,0.000000 }, - { 213, 213, 0, 0, 1613, 0,0.000000 }, - { 214, 215, 0, 0, 3260, 3260,0.000000 }, - { 216, 217, 0, 0, 360, 360,0.000000 }, - { 218, 219, 0, 0, 1020, 1020,0.000000 }, - { 220, 221, 0, 0, 2126, 2126,0.000000 }, - { 222, 223, 0, 0, 300, 13,0.000000 }, - { 224, 224, 0, 0, 1740, 1740,0.000000 }, - { 225, 226, 0, 0, 1720, 1720,0.000000 }, - { 227, 227, 0, 0, 146, 146,0.000000 }, - { 228, 228, 0, 0, 186, 40,0.000000 }, - { 229, 230, 0, 0, 40000, 46,0.000000 }, - { 231, 232, 0, 0, 40000, 66,0.000000 }, - { 233, 234, 0, 0, 40000, 266,0.000000 }, - { 235, 236, 0, 0, 160, 160,0.000000 }, - { 235, 237, 0, 0, 386, 386,0.000000 }, - { 46, 238, 0, 0, 1046, 1046,0.000000 }, - { 239, 240, 0, 0, 40000, 66,0.000000 }, - { 241, 242, 0, 0, 720, 46,0.000000 }, - { 243, 243, 0, 0, 40000, 33,0.000000 }, - { 244, 244, 0, 0, 40000, 6,0.000000 }, - { 245, 245, 0, 0, 40000, 13,0.000000 }, - { 246, 247, 0, 0, 466, 466,0.000000 }, - { 248, 249, 0, 0, 1213, 13,0.000000 }, - { 250, 250, 0, 0, 60, 6,0.000000 }, - { 251, 251, 0, 0, 40000, 66,0.000000 }, - { 252, 253, 0, 0, 40000, 6,0.000000 }, - { 254, 255, 0, 0, 40000, 26,0.000000 }, - { 256, 257, 0, 0, 166, 0,0.000000 }, - { 258, 259, 0, 0, 40000, 6,0.000000 }, - { 260, 261, 0, 0, 40000, 20,0.000000 }, - { 262, 263, 0, 0, 40000, 26,0.000000 }, - { 264, 265, 0, 0, 40000, 40,0.000000 }, - { 266, 267, 0, 0, 40000, 6,0.000000 }, - { 268, 269, 0, 0, 40000, 20,0.000000 }, - { 270, 271, 0, 0, 40000, 13,0.000000 }, - { 272, 273, 0, 0, 40000, 60,0.000000 }, - { 274, 275, 0, 0, 40000, 33,0.000000 }, - { 276, 276, 0, 0, 40000, 20,0.000000 }, - { 277, 278, 0, 0, 40000, 73,0.000000 }, - { 279, 280, 0, 0, 40000, 33,0.000000 }, - { 281, 282, 0, 0, 40000, 73,0.000000 }, - { 283, 283, 0, 0, 40000, 13,0.000000 }, - { 284, 285, 0, 0, 40000, 6,0.000000 }, - { 286, 287, 0, 0, 40000, 20,0.000000 }, - { 288, 288, 0, 0, 40000, 33,0.000000 }, - { 289, 290, 0, 0, 40000, 6,0.000000 }, - { 291, 292, 0, 0, 40000, 73,0.000000 }, - { 293, 294, 0, 0, 40000, 106,0.000000 }, - { 295, 296, 0, 0, 40000, 180,0.000000 }, - { 88, 297, 0, 0, 40000, 500,0.000000 }, - { 298, 299, 0, 0, 40000, 26,0.000000 }, - { 300, 301, 0, 0, 40000, 553,0.000000 }, - { 302, 302, 0, 0, 40000, 126,0.000000 }, - { 303, 303, 0, 0, 40000, 53,0.000000 }, - { 304, 304, 0, 0, 1793, 1793,0.000000 }, - { 305, 306, 0, 0, 40000, 300,0.000000 }, - { 307, 307, 0, 0, 1900, 1900,0.000000 }, - { 308, 308, 0, 0, 146, 146,0.000000 }, - { 309, 309, 0, 0, 40000, 580,0.000000 }, - { 310, 310, 0, 0, 40000, 480,0.000000 }, - { 311, 312, 0, 0, 2273, 2273,0.000000 }, - { 313, 314, 0, 0, 1140, 1140,0.000000 }, - { 315, 316, 0, 0, 560, 560,0.000000 }, - { 317, 318, 0, 0, 1080, 1080,0.000000 }, - { 107, 319, 0, 0, 280, 280,0.000000 }, - { 108, 320, 0, 0, 40000, 6,0.000000 }, - { 109, 321, 0, 0, 40000, 46,0.000000 }, - { 322, 323, 0, 0, 40000, 6,0.000000 }, - { 324, 325, 0, 0, 146, 146,0.000000 }, - { 326, 327, 0, 0, 246, 246,0.000000 }, - { 328, 328, 0, 0, 26, 26,0.000000 }, - { 329, 329, 0, 0, 140, 140,0.000000 }, - { 330, 331, 0, 0, 40, 40,0.000000 }, - { 332, 332, 0, 0, 2313, 2313,0.000000 }, - { 333, 333, 0, 0, 86, 86,0.000000 }, - { 334, 334, 0, 0, 3440, 3440,0.000000 }, - { 335, 335, 0, 0, 146, 146,0.000000 }, - { 336, 336, 0, 0, 2406, 2406,0.000000 }, - { 337, 337, 0, 0, 40000, 146,0.000000 }, - { 338, 339, 0, 0, 40000, 113,0.000000 }, - { 340, 341, 0, 0, 40000, 0,0.000000 }, - { 342, 342, 35, 0, 446, 446,0.000000 }, - { 343, 343, 0, 0, 20, 20,0.000000 }, - { 344, 344, 35, 0, 86, 86,0.000000 }, - { 345, 345, 35, 0, 26, 26,0.000000 }, - { 346, 346, 50, 0, 153, 153,0.000000 }, - { 347, 347, 18, 0, 53, 53,0.000000 }, - { 348, 348, 72, 0, 53, 53,0.000000 }, - { 349, 349, 74, 0, 33, 33,0.000000 }, - { 350, 350, 35, 0, 66, 66,0.000000 }, - { 351, 351, 16, 0, 86, 86,0.000000 }, - { 352, 352, 0, 0, 1513, 13,0.000000 }, - { 353, 353, 38, 0, 53, 53,0.000000 }, - { 354, 354, 38, 0, 100, 100,0.000000 }, - { 355, 355, 31, 0, 33, 33,0.000000 }, - { 355, 355, 35, 0, 33, 33,0.000000 }, - { 355, 355, 38, 0, 193, 193,0.000000 }, - { 355, 355, 41, 0, 166, 166,0.000000 }, - { 355, 355, 45, 0, 126, 126,0.000000 }, - { 355, 355, 50, 0, 146, 146,0.000000 }, - { 356, 356, 36, 0, 100, 100,0.000000 }, - { 357, 357, 36, 0, 26, 26,0.000000 }, - { 358, 358, 48, 0, 73, 73,0.000000 }, - { 358, 358, 36, 0, 100, 100,0.000000 }, - { 359, 359, 36, 0, 20, 20,0.000000 }, - { 360, 360, 0, 0, 33, 33,0.000000 }, - { 361, 361, 61, 0, 60, 60,0.000000 }, - { 362, 362, 96, 0, 233, 233,0.000000 }, - { 363, 363, 38, 0, 60, 60,0.000000 }, - { 127, 127, 16, 0, 66, 66,0.000000 }, - { 364, 365, 18, 0, 13, 13,0.000000 }, - { 366, 366, 30, 0, 106, 106,0.000000 }, - { 367, 368, 35, 0, 73, 73,0.000000 }, - { 129, 129, 0, 0, 73, 73,0.000000 }, - { 369, 369, 0, 0, 66, 66,0.000000 }, - { 370, 370, 88, 0, 86, 86,0.000000 }, - { 371, 371, 88, 0, 60, 60,0.000000 }, - { 372, 372, 79, 0, 380, 380,0.000000 }, - { 135, 135, 14, 0, 860, 860,0.000000 }, - { 373, 373, 46, 0, 313, 313,0.000000 }, - { 374, 375,129, 0, 1613, 60,0.000000 }, - { 376, 376, 58, 0, 140, 140,0.000000 }, - { 377, 377,164, 0, 106, 106,0.000000 }, - { 378, 378,142, 0, 2300, 2300,0.000000 }, - { 379, 379, 9, 0, 40, 40,0.000000 }, - { 380, 381, 35, 0, 3306, 0,0.000000 }, - { 382, 382, 28, 0, 26, 26,0.000000 }, - { 383, 383, 46, 0, 320, 320,0.000000 }, - { 384, 384, 60, 0, 93, 93,0.000000 }, - { 384, 384, 54, 0, 100, 100,0.000000 }, - { 385, 385, 72, 0, 60, 60,0.000000 }, - { 385, 385, 67, 0, 60, 60,0.000000 }, - { 385, 385, 60, 0, 53, 53,0.000000 }, - { 386, 386, 1, 0, 46, 46,0.000000 }, - { 387, 387, 77, 0, 133, 133,0.000000 }, - { 387, 387, 72, 0, 133, 133,0.000000 }, - { 388, 388, 90, 0, 46, 46,0.000000 }, - { 389, 389, 39, 0, 180, 180,0.000000 }, - { 390, 390, 36, 0, 506, 506,0.000000 }, - { 391, 392, 35, 0, 20, 20,0.000000 }, - { 391, 393, 35, 0, 20, 20,0.000000 }, - { 394, 394, 60, 0, 40, 40,0.000000 }, - { 328, 328, 7, 0, 26, 26,0.000000 }, - { 395, 395, 90, 0, 80, 80,0.000000 }, - { 396, 396, 90, 0, 306, 306,0.000000 }, - { 397, 397, 35, 0, 106, 106,0.000000 }, - { 398, 399, 5, 0, 506, 506,0.000000 }, - { 400, 400,103, 0, 220, 220,0.000000 }, - { 401, 401, 3, 0, 6, 6,0.000000 }, - { 169, 169, 1, 0, 40, 40,0.000000 }, - { 131, 131, 0, 0, 40, 40,0.000000 }, - { 402, 402, 36, 0, 180, 180,0.000000 }, - { 403, 403, 60, 0, 40000, 0,0.000000 }, - { 404, 404, 37, 0, 60, 60,0.000000 }, - { 405, 405, 36, 0, 46, 46,0.000000 }, - { 406, 406, 32, 0, 40, 40,0.000000 }, - { 407, 407, 50, 0, 306, 306,0.000000 }, - { 408, 408, 50, 0, 93, 93,0.000000 }, - { 409, 409, 83, 0, 26, 26,0.000000 }, - { 410, 410, 72, 0, 93, 93,0.000000 }, - { 148, 148, 59, 0, 153, 153,0.000000 }, - { 411, 411, 64, 0, 40, 40,0.000000 }, - { 411, 411, 60, 0, 40, 40,0.000000 }, - { 412, 412, 72, 0, 26, 26,0.000000 }, - { 412, 412, 62, 0, 33, 33,0.000000 }, - { 413, 413, 83, 0, 273, 273,0.000000 }, - { 414, 414, 0, 0, 40000, 13,0.000000 }, - { 415, 415, 0, 0, 1126, 1126,0.000000 }, - { 416, 416, 0, 0, 40000, 20,0.000000 }, - { 417, 417, 0, 0, 2940, 20,0.000000 }, - { 418, 418, 0, 0, 2233, 2233,0.000000 }, - { 419, 419, 0, 0, 1233, 1233,0.000000 }, - { 420, 420, 0, 0, 940, 940,0.000000 }, - { 421, 421, 0, 0, 1580, 1580,0.000000 }, - { 422, 422, 0, 0, 1740, 1740,0.000000 }, - { 423, 423, 0, 0, 140, 140,0.000000 }, - { 424, 424, 0, 0, 940, 940,0.000000 }, - { 425, 425, 0, 0, 1080, 1080,0.000000 }, - { 426, 426, 0, 0, 2086, 2086,0.000000 }, - { 427, 427, 0, 0, 40000, 26,0.000000 }, - { 428, 428, 60, 0, 40000, 0,0.000000 }, - { 429, 429, 73, 0, 473, 473,0.000000 }, - { 429, 429, 74, 0, 473, 473,0.000000 }, - { 429, 429, 80, 0, 473, 473,0.000000 }, - { 429, 429, 84, 0, 473, 473,0.000000 }, - { 429, 429, 92, 0, 400, 400,0.000000 }, - { 430, 430, 81, 0, 280, 280,0.000000 }, - { 430, 430, 83, 0, 280, 280,0.000000 }, - { 430, 430, 95, 0, 220, 220,0.000000 }, - { 431, 431, 35, 0, 46, 46,0.000000 }, - { 432, 432, 60, 0, 40, 40,0.000000 }, - { 357, 357, 59, 0, 13, 13,0.000000 }, - { 432, 432, 44, 0, 40, 40,0.000000 }, - { 433, 433, 41, 0, 166, 166,0.000000 }, - { 434, 434, 97, 0, 26, 26,0.000000 }, - { 433, 433, 44, 0, 140, 140,0.000000 }, - { 433, 433, 48, 0, 153, 153,0.000000 }, - { 435, 435, 96, 0, 233, 233,0.000000 }, - { 433, 433, 51, 0, 160, 160,0.000000 }, - { 433, 433, 54, 0, 160, 160,0.000000 }, - { 436, 436, 40, 0, 386, 386,0.000000 }, - { 433, 433, 57, 0, 113, 113,0.000000 }, - { 437, 437, 58, 0, 120, 120,0.000000 }, - { 438, 438, 97, 0, 73, 73,0.000000 }, - { 439, 439, 50, 0, 60, 60,0.000000 }, - { 437, 437, 60, 0, 153, 153,0.000000 }, - { 440, 440, 53, 0, 53, 53,0.000000 }, - { 441, 441, 46, 0, 46, 46,0.000000 }, - { 440, 440, 57, 0, 53, 53,0.000000 }, - { 442, 442, 42, 0, 206, 206,0.000000 }, - { 442, 442, 37, 0, 206, 206,0.000000 }, - { 443, 443, 41, 0, 193, 193,0.000000 }, - { 443, 443, 37, 0, 193, 193,0.000000 }, - { 444, 444, 77, 0, 46, 46,0.000000 }, - { 444, 444, 72, 0, 46, 46,0.000000 }, - { 445, 445, 70, 0, 60, 60,0.000000 }, - { 445, 445, 90, 0, 60, 60,0.000000 }, - { 446, 446, 46, 0, 46, 46,0.000000 }, - { 447, 447, 48, 0, 246, 246,0.000000 }, - { 448, 448, 85, 0, 20, 20,0.000000 }, - { 449, 449, 66, 0, 60, 60,0.000000 }, - { 449, 449, 61, 0, 60, 60,0.000000 }, - { 450, 450, 41, 0, 106, 106,0.000000 }, - { 451, 451, 41, 0, 140, 140,0.000000 }, - { 452, 452, 81, 0, 66, 66,0.000000 }, - { 400, 400, 81, 0, 266, 266,0.000000 }, - { 400, 400, 76, 0, 266, 266,0.000000 }, - { 359, 359, 60, 0, 13, 13,0.000000 }, - { 453, 453, 53, 0, 120, 120,0.000000 }, - { 454, 454, 0, 0, 40000, 0,0.000000 }, - { 455, 455, 0, 0, 40, 40,0.000000 }, - { 456, 456, 0, 0, 1080, 1080,0.000000 }, - { 457, 457, 0, 0, 126, 126,0.000000 }, - { 458, 458, 0, 0, 40000, 26,0.000000 }, - { 459, 459, 0, 0, 40000, 6,0.000000 }, - { 460, 460, 0, 0, 700, 700,0.000000 }, - { 461, 461, 0, 0, 280, 280,0.000000 }, - { 462, 462, 0, 0, 360, 360,0.000000 }, - { 463, 463, 0, 0, 40000, 20,0.000000 }, - { 464, 464, 0, 0, 1466, 13,0.000000 }, - { 465, 465, 0, 0, 40000, 33,0.000000 }, - { 466, 466, 0, 0, 40000, 33,0.000000 }, - { 467, 467, 0, 0, 1953, 1953,0.000000 }, - { 468, 468, 0, 0, 1580, 1580,0.000000 }, - { 469, 469, 0, 0, 1340, 1340,0.000000 }, - { 470, 470, 0, 0, 40000, 0,0.000000 }, - { 471, 471, 0, 0, 40000, 53,0.000000 }, - { 472, 472, 0, 0, 1386, 1386,0.000000 }, - { 473, 473, 0, 0, 560, 13,0.000000 }, - { 474, 474, 0, 0, 40000, 66,0.000000 }, - { 475, 475, 0, 0, 593, 593,0.000000 }, - { 476, 476, 0, 0, 40000, 2446,0.000000 }, - { 477, 477, 0, 0, 60, 60,0.000000 }, - { 478, 478, 0, 0, 220, 220,0.000000 }, - { 479, 479, 0, 0, 153, 153,0.000000 }, - { 480, 480, 0, 0, 20, 20,0.000000 }, - { 481, 481, 0, 0, 40000, 0,0.000000 }, - { 482, 482, 0, 0, 753, 753,0.000000 }, - { 483, 483, 0, 0, 100, 100,0.000000 }, - { 484, 484, 0, 0, 40000, 73,0.000000 }, - { 485, 485, 0, 0, 2600, 320,0.000000 }, - { 486, 486, 0, 0, 293, 293,0.000000 }, - { 487, 487, 0, 0, 1400, 1400,0.000000 }, - { 488, 488, 0, 0, 2073, 2073,0.000000 }, - { 489, 489, 0, 0, 80, 80,0.000000 }, - { 490, 490, 0, 0, 40000, 33,0.000000 }, - { 491, 491, 50, 0, 446, 446,0.000000 }, - { 492, 492, 37, 0, 46, 46,0.000000 }, - { 493, 493, 39, 0, 180, 180,0.000000 }, - { 494, 494, 39, 0, 33, 33,0.000000 }, - { 495, 495, 86, 0, 1800, 1800,0.000000 }, - { 496, 496, 43, 0, 33, 33,0.000000 }, - { 127, 127, 24, 0, 46, 46,0.000000 }, - { 127, 127, 29, 0, 33, 33,0.000000 }, - { 497, 497, 50, 0, 153, 153,0.000000 }, - { 498, 498, 30, 0, 100, 100,0.000000 }, - { 498, 498, 33, 0, 413, 413,0.000000 }, - { 498, 498, 38, 0, 1633, 1633,0.000000 }, - { 498, 498, 42, 0, 26, 26,0.000000 }, - { 499, 499, 24, 0, 46, 46,0.000000 }, - { 499, 499, 27, 0, 66, 66,0.000000 }, - { 499, 499, 29, 0, 66, 66,0.000000 }, - { 499, 499, 32, 0, 53, 53,0.000000 }, - { 500, 500, 32, 0, 13, 13,0.000000 }, - { 501, 501, 53, 0, 86, 86,0.000000 }, - { 501, 501, 57, 0, 86, 86,0.000000 }, - { 502, 502, 60, 0, 80, 80,0.000000 }, - { 503, 503, 55, 0, 160, 160,0.000000 }, - { 486, 486, 85, 0, 266, 266,0.000000 }, - { 504, 504, 90, 0, 453, 453,0.000000 }, - { 505, 505, 84, 0, 73, 73,0.000000 }, - { 506, 506, 48, 0, 160, 160,0.000000 }, - { 507, 507, 48, 0, 40, 40,0.000000 }, - { 132, 132, 72, 0, 13, 13,0.000000 }, - { 508, 508, 72, 0, 13, 13,0.000000 }, - { 509, 509, 72, 0, 13, 13,0.000000 }, - { 510, 510, 63, 0, 533, 533,0.000000 }, - { 510, 510, 65, 0, 526, 526,0.000000 }, - { 511, 511, 79, 0, 506, 506,0.000000 }, - { 512, 512, 38, 0, 113, 113,0.000000 }, - { 513, 513, 94, 0, 100, 100,0.000000 }, - { 514, 514, 87, 0, 113, 113,0.000000 }, - { 514, 514, 94, 0, 100, 100,0.000000 }, - { 515, 515, 80, 0, 66, 66,0.000000 }, - { 516, 516, 47, 0, 140, 140,0.000000 }, - { 517, 517, 61, 0, 80, 80,0.000000 }, - { 517, 517, 68, 0, 66, 66,0.000000 }, - { 518, 518, 61, 0, 160, 160,0.000000 }, - { 518, 518, 68, 0, 126, 126,0.000000 }, - { 499, 499, 60, 0, 46, 46,0.000000 }, - { 519, 519, 60, 0, 60, 60,0.000000 }, - { 520, 520, 36, 0, 53, 53,0.000000 }, - { 520, 520, 60, 0, 40, 40,0.000000 }, - { 521, 521, 60, 0, 40, 40,0.000000 }, - { 522, 522, 68, 0, 20, 20,0.000000 }, - { 523, 523, 71, 0, 33, 33,0.000000 }, - { 523, 523, 72, 0, 33, 33,0.000000 }, - { 524, 524,101, 0, 320, 320,0.000000 }, - { 525, 525, 36, 0, 1680, 1680,0.000000 }, - { 526, 526, 25, 0, 40000, 2286,0.000000 }, - { 527, 527, 37, 0, 400, 400,0.000000 }, - { 528, 528, 36, 0, 146, 146,0.000000 }, - { 528, 528, 41, 0, 166, 166,0.000000 }, - { 529, 529, 84, 0, 73, 73,0.000000 }, - { 530, 530, 54, 0, 1326, 1326,0.000000 }, - { 481, 481, 48, 0, 40000, 0,0.000000 }, - { 531, 531, 0, 0, 2266, 2266,0.000000 }, - { 532, 532, 0, 0, 833, 833,0.000000 }, - { 533, 533, 0, 0, 246, 13,0.000000 }, - { 534, 534, 0, 0, 40000, 6,0.000000 }, - { 535, 535, 0, 0, 4140, 26,0.000000 }, - { 536, 536, 0, 0, 3886, 13,0.000000 }, - { 537, 537, 0, 0, 4886, 4886,0.000000 }, - { 538, 538, 0, 0, 1780, 1780,0.000000 }, - { 539, 539, 0, 0, 4140, 26,0.000000 }, - { 540, 540, 0, 0, 40000, 6,0.000000 }, - { 541, 541, 0, 0, 3946, 13,0.000000 }, - { 542, 542, 0, 0, 40, 40,0.000000 }, - { 543, 543, 0, 0, 40000, 13,0.000000 }, - { 544, 544, 0, 0, 4426, 4426,0.000000 }, - { 545, 545, 0, 0, 40000, 493,0.000000 }, - { 546, 546, 0, 0, 40000, 846,0.000000 }, - { 547, 547, 0, 0, 40000, 53,0.000000 }, - { 135, 135, 49, 0, 1146, 1146,0.000000 }, - { 548, 548, 35, 0, 40, 40,0.000000 }, - { 549, 549, 41, 0, 6, 6,0.000000 }, - { 366, 366, 38, 0, 106, 106,0.000000 }, - { 550, 550, 39, 0, 26, 26,0.000000 }, - { 551, 551, 49, 0, 46, 46,0.000000 }, - { 408, 408, 59, 0, 93, 93,0.000000 }, - { 552, 552, 24, 0, 26, 26,0.000000 }, - { 552, 552, 27, 0, 40, 20,0.000000 }, - { 552, 552, 29, 0, 20, 20,0.000000 }, - { 552, 552, 32, 0, 40, 13,0.000000 }, - { 553, 553, 84, 0, 113, 113,0.000000 }, - { 512, 512, 79, 0, 73, 73,0.000000 }, - { 554, 554, 61, 0, 173, 173,0.000000 }, - { 554, 554, 68, 0, 133, 133,0.000000 }, - { 555, 555, 36, 0, 33, 33,0.000000 }, - { 555, 555, 60, 0, 20, 20,0.000000 }, - { 556, 556, 36, 0, 180, 180,0.000000 }, - { 115, 115, 37, 0, 46, 46,0.000000 }, - { 557, 557, 0, 0, 1066, 1066,0.000000 }, - { 558, 558, 0, 0, 273, 273,0.000000 }, - { 559, 559, 0, 0, 186, 186,0.000000 }, - { 560, 560, 0, 0, 966, 966,0.000000 }, - { 561, 561, 0, 0, 80, 80,0.000000 }, - { 562, 562, 0, 0, 326, 326,0.000000 }, - { 563, 563, 0, 0, 40000, 33,0.000000 }, - { 564, 564, 0, 0, 380, 380,0.000000 }, - { 565, 565, 0, 0, 40, 40,0.000000 }, - { 566, 566, 0, 0, 4586, 4586,0.000000 }, - { 567, 567, 0, 0, 2680, 2680,0.000000 }, - { 568, 568, 0, 0, 40000, 6,0.000000 }, - { 569, 569, 0, 0, 80, 80,0.000000 }, - { 570, 570, 0, 0, 1206, 1206,0.000000 }, - { 571, 571, 0, 0, 593, 593,0.000000 }, - { 572, 572, 0, 0, 680, 680,0.000000 }, - { 356, 356, 0, 0, 246, 246,0.000000 }, - { 573, 573, 0, 0, 40000, 20,0.000000 }, - { 574, 574, 0, 0, 40000, 20,0.000000 }, - { 575, 575, 0, 0, 40000, 73,0.000000 }, - { 576, 576, 0, 0, 40000, 53,0.000000 }, - { 577, 577, 0, 0, 40000, 33,0.000000 }, - { 578, 578, 0, 0, 40000, 140,0.000000 }, - { 579, 579, 0, 0, 40000, 93,0.000000 }, - { 580, 580, 0, 0, 40000, 126,0.000000 }, - { 581, 581, 0, 0, 40000, 26,0.000000 }, - { 582, 582, 0, 0, 40000, 53,0.000000 }, - { 583, 583, 0, 0, 513, 513,0.000000 }, - { 584, 584, 0, 0, 40000, 66,0.000000 }, - { 585, 585, 0, 0, 313, 313,0.000000 }, - { 516, 516, 0, 0, 140, 140,0.000000 }, - { 586, 586, 0, 0, 40000, 0,0.000000 }, - { 587, 587, 0, 0, 40000, 0,0.000000 }, - { 588, 588, 0, 0, 40000, 6,0.000000 }, - { 498, 498, 26, 0, 86, 86,0.000000 }, - { 494, 494, 35, 0, 53, 53,0.000000 }, - { 350, 350, 41, 0, 80, 80,0.000000 }, - { 353, 353, 48, 0, 40, 40,0.000000 }, - { 354, 354, 67, 0, 73, 73,0.000000 }, - { 502, 502, 24, 0, 100, 100,0.000000 }, - { 346, 346, 36, 0, 46, 46,0.000000 }, - { 346, 346, 38, 0, 193, 193,0.000000 }, - { 346, 346, 40, 0, 140, 140,0.000000 }, - { 346, 346, 42, 0, 173, 173,0.000000 }, - { 346, 346, 44, 0, 140, 140,0.000000 }, - { 510, 510, 55, 0, 453, 453,0.000000 }, - { 346, 346, 46, 0, 146, 146,0.000000 }, - { 136, 136, 80, 0, 486, 486,0.000000 }, - { 486, 486, 24, 0, 346, 346,0.000000 }, - { 153, 153, 50, 0, 13, 13,0.000000 }, - { 346, 346, 24, 0, 66, 66,0.000000 }, - { 516, 516, 31, 0, 186, 186,0.000000 }, - { 498, 498, 35, 0, 40, 40,0.000000 }, - { 517, 517, 60, 0, 80, 80,0.000000 }, - { 530, 530, 36, 0, 1760, 1760,0.000000 }, - { 530, 530, 48, 0, 1360, 6,0.000000 }, - { 589, 589, 0, 0, 1660, 1660,0.000000 }, - { 139, 139, 76, 0, 73, 73,0.000000 }, - { 156, 156, 48, 0, 80, 80,0.000000 }, - { 157, 157, 48, 0, 226, 226,0.000000 }, - { 165, 165, 69, 0, 40, 40,0.000000 }, - { 167, 167, 75, 0, 133, 133,0.000000 }, - { 590, 590, 0, 0, 1226, 1226,0.000000 }, - { 591, 591, 0, 0, 2193, 2193,0.000000 }, - { 592, 592, 0, 0, 1900, 1900,0.000000 }, - { 593, 593, 0, 0, 626, 626,0.000000 }, - { 594, 594, 0, 0, 1213, 1213,0.000000 }, - { 595, 595, 0, 0, 1740, 1740,0.000000 }, - { 596, 596, 0, 0, 193, 193,0.000000 }, - { 597, 597, 0, 0, 300, 300,0.000000 }, - { 598, 598, 0, 0, 40000, 6,0.000000 }, - { 599, 599, 0, 0, 40000, 480,0.000000 }, - { 600, 600, 0, 0, 40000, 20,0.000000 }, - { 601, 601, 0, 0, 653, 653,0.000000 }, - { 602, 602, 0, 0, 126, 126,0.000000 }, - { 603, 603, 0, 0, 1080, 1080,0.000000 }, - { 604, 604, 0, 0, 4200, 4200,0.000000 }, - { 605, 605, 0, 0, 1020, 1020,0.000000 }, - { 606, 606, 0, 0, 593, 13,0.000000 }, - { 607, 607, 0, 0, 80, 60,0.000000 }, - { 608, 608, 0, 0, 40000, 113,0.000000 }, - { 609, 609, 0, 0, 120, 120,0.000000 }, - { 610, 610, 0, 0, 1580, 1580,0.000000 }, - { 611, 611, 0, 0, 460, 460,0.000000 }, - { 612, 612, 0, 0, 40000, 53,0.000000 }, - { 613, 613, 0, 0, 2320, 13,0.000000 }, - { 614, 614, 0, 0, 80, 60,0.000000 }, - { 615, 615, 0, 0, 80, 60,0.000000 }, - { 616, 616, 0, 0, 1020, 1020,0.000000 }, - { 617, 617, 0, 0, 146, 146,0.000000 }, - { 618, 618, 0, 0, 740, 740,0.000000 }, - { 619, 619, 0, 0, 146, 146,0.000000 }, - { 620, 620, 0, 0, 40000, 6,0.000000 }, - { 621, 621, 0, 0, 913, 913,0.000000 }, - { 622, 622, 0, 0, 2280, 2280,0.000000 }, - { 623, 623, 0, 0, 166, 6,0.000000 }, - { 624, 624, 0, 0, 40000, 0,0.000000 }, - { 625, 625, 0, 0, 40000, 0,0.000000 }, - { 626, 626, 0, 0, 40000, 0,0.000000 }, - { 627, 627, 0, 0, 1046, 1046,0.000000 }, - { 628, 628, 0, 0, 40000, 6,0.000000 }, - { 629, 629, 0, 0, 40000, 0,0.000000 }, - { 630, 630, 0, 0, 1953, 1953,0.000000 }, - { 631, 631, 0, 0, 40000, 106,0.000000 }, - { 632, 632, 0, 0, 533, 13,0.000000 }, - { 633, 633, 0, 0, 2273, 2273,0.000000 }, - { 634, 634, 0, 0, 646, 646,0.000000 }, - { 635, 635, 0, 0, 166, 166,0.000000 }, - { 636, 636, 0, 0, 326, 326,0.000000 }, - { 637, 637, 0, 0, 40000, 26,0.000000 }, - { 638, 638, 0, 0, 246, 246,0.000000 }, - { 346, 346, 0, 0, 140, 140,0.000000 }, - { 639, 639, 0, 0, 1226, 1226,0.000000 }, - { 404, 404, 0, 0, 146, 146,0.000000 }, - { 506, 506, 0, 0, 153, 153,0.000000 }, - { 639, 639, 60, 0, 886, 886,0.000000 }, - { 639, 639, 79, 0, 446, 446,0.000000 }, - { 640, 640, 65, 0, 800, 800,0.000000 }, - { 486, 486, 31, 0, 353, 353,0.000000 }, - { 486, 486, 36, 0, 360, 360,0.000000 }, - { 640, 640, 72, 0, 613, 613,0.000000 }, - { 136, 136, 79, 0, 493, 493,0.000000 }, - { 148, 148, 57, 0, 160, 160,0.000000 }, - { 150, 150, 53, 0, 153, 153,0.000000 }, - { 641, 641, 84, 0, 106, 106,0.000000 }, - { 520, 520, 66, 0, 40, 40,0.000000 }, - { 642, 642, 31, 0, 166, 13,0.000000 }, - { 642, 642, 29, 0, 60, 26,0.000000 }, - { 356, 356, 31, 0, 93, 93,0.000000 }, - { 356, 356, 19, 0, 220, 220,0.000000 }, - { 643, 643, 31, 0, 40000, 6,0.000000 }, - { 643, 643, 29, 0, 40000, 6,0.000000 }, - { 644, 644, 31, 0, 560, 560,0.000000 }, - { 644, 644, 35, 0, 573, 573,0.000000 }, - { 644, 644, 40, 0, 526, 526,0.000000 }, - { 644, 644, 47, 0, 540, 540,0.000000 }, - { 516, 516, 32, 0, 186, 186,0.000000 }, - { 516, 516, 43, 0, 146, 146,0.000000 }, - { 495, 495, 26, 0, 60, 60,0.000000 }, - { 495, 495, 44, 0, 380, 380,0.000000 }, - { 496, 496, 26, 0, 26, 26,0.000000 }, - { 496, 496, 51, 0, 40, 40,0.000000 }, - { 496, 496, 39, 0, 33, 33,0.000000 }, - { 495, 495, 30, 0, 46, 46,0.000000 }, - { 645, 645, 44, 0, 486, 486,0.000000 }, - { 645, 645, 43, 0, 473, 473,0.000000 }, - { 646, 646, 0, 0, 653, 653,0.000000 }, - { 647, 647, 0, 0, 2280, 2280,0.000000 }, - { 648, 648, 0, 0, 526, 526,0.000000 }, - { 649, 649, 0, 0, 40000, 40,0.000000 }, - { 650, 650, 0, 0, 40, 40,0.000000 }, - { 651, 651, 0, 0, 933, 933,0.000000 }, - { 652, 652, 0, 0, 40000, 300,0.000000 }, - { 653, 653, 0, 0, 280, 280,0.000000 }, - { 654, 654, 0, 0, 40000, 6,0.000000 }, - { 655, 655, 0, 0, 40000, 0,0.000000 }, - { 656, 656, 0, 0, 40000, 6,0.000000 }, - { 657, 657, 0, 0, 280, 280,0.000000 }, - { 658, 658, 0, 0, 513, 513,0.000000 }, - { 659, 659, 0, 0, 40000, 6,0.000000 }, - { 660, 660, 0, 0, 600, 600,0.000000 }, - { 661, 661, 0, 0, 646, 646,0.000000 }, - { 662, 662, 0, 0, 1166, 1166,0.000000 }, - { 663, 663, 0, 0, 40, 40,0.000000 }, - { 664, 664, 0, 0, 2073, 2073,0.000000 }, - { 665, 665, 0, 0, 40000, 106,0.000000 }, - { 666, 666, 0, 0, 40000, 146,0.000000 }, - { 667, 667, 0, 0, 40000, 126,0.000000 }, - { 668, 668, 0, 0, 280, 280,0.000000 }, - { 669, 669, 0, 0, 40000, 73,0.000000 }, - { 670, 670, 0, 0, 393, 393,0.000000 }, - { 671, 671, 0, 0, 760, 760,0.000000 }, - { 672, 672, 0, 0, 40000, 233,0.000000 }, - { 673, 673, 0, 0, 253, 253,0.000000 }, - { 674, 674, 0, 0, 186, 186,0.000000 }, - { 675, 675, 0, 0, 40000, 46,0.000000 }, - { 676, 676, 0, 0, 4773, 4773,0.000000 }, - { 677, 677, 0, 0, 2186, 2186,0.000000 }, - { 678, 678, 0, 0, 313, 313,0.000000 }, - { 679, 679, 0, 0, 1226, 1226,0.000000 }, - { 680, 680, 0, 0, 526, 13,0.000000 }, - { 681, 681, 0, 0, 40000, 0,0.000000 }, - { 682, 682, 0, 0, 40, 46,0.000000 }, - { 683, 683, 0, 0, 146, 146,0.000000 }, - { 684, 684, 0, 0, 2193, 2193,0.000000 }, - { 685, 685, 0, 0, 40000, 220,0.000000 }, - { 686, 686, 0, 0, 40000, 560,0.000000 }, - { 687, 687, 0, 0, 86, 86,0.000000 }, - { 688, 688, 0, 0, 40000, 1326,0.000000 }, - { 689, 689, 0, 0, 1166, 1166,0.000000 }, - { 690, 690, 0, 0, 593, 593,0.000000 }, - { 691, 691, 0, 0, 1580, 1580,0.000000 }, - { 692, 692, 0, 0, 513, 513,0.000000 }, - { 693, 693, 0, 0, 333, 333,0.000000 }, - { 694, 694, 0, 0, 1200, 1200,0.000000 }, - { 695, 695, 0, 0, 40000, 6,0.000000 }, - { 645, 645, 0, 0, 486, 486,0.000000 }, - { 696, 696, 0, 0, 40000, 6,0.000000 }, - { 697, 697, 0, 0, 333, 333,0.000000 }, - { 698, 698, 0, 0, 120, 120,0.000000 }, - { 699, 699, 0, 0, 40000, 6,0.000000 }, - { 700, 700, 0, 0, 13, 13,0.000000 }, - { 701, 701, 0, 0, 40000, 53,0.000000 }, - { 702, 702, 0, 0, 806, 806,0.000000 }, - { 703, 703, 0, 0, 40000, 6,0.000000 }, - { 704, 704, 0, 0, 40000, 6,0.000000 }, - { 705, 705, 0, 0, 40000, 0,0.000000 }, - { 706, 706, 0, 0, 40000, 6,0.000000 }, - { 707, 707, 0, 0, 40000, 166,0.000000 }, - { 708, 708, 0, 0, 40000, 26,0.000000 }, - { 709, 709, 0, 0, 40000, 146,0.000000 }, - { 710, 710, 0, 0, 1233, 6,0.000000 }, - { 711, 711, 0, 0, 146, 146,0.000000 }, - { 712, 712, 0, 0, 40000, 6,0.000000 }, - { 713, 713, 0, 0, 40000, 66,0.000000 }, - { 714, 714, 0, 0, 40000, 393,0.000000 }, - { 715, 715, 0, 0, 40000, 93,0.000000 }, - { 716, 716, 0, 0, 620, 620,0.000000 }, - { 717, 717, 0, 0, 40000, 6,0.000000 }, - { 718, 718, 0, 0, 493, 493,0.000000 }, - { 719, 719, 0, 0, 280, 280,0.000000 }, - { 720, 720, 0, 0, 760, 760,0.000000 }, - { 721, 721, 0, 0, 160, 160,0.000000 }, - { 722, 722, 0, 0, 40000, 106,0.000000 }, - { 723, 723, 0, 0, 166, 166,0.000000 }, - { 724, 724, 0, 0, 40000, 6,0.000000 }, - { 725, 725, 0, 0, 126, 126,0.000000 }, - { 726, 726, 0, 0, 593, 593,0.000000 }, - { 727, 727, 0, 0, 513, 513,0.000000 }, - { 728, 728, 0, 0, 246, 246,0.000000 }, - { 507, 507, 0, 0, 40, 40,0.000000 }, - { 512, 512, 0, 0, 93, 93,0.000000 }, - { 729, 729, 0, 0, 2406, 2406,0.000000 }, - { 730, 730, 0, 0, 2400, 2400,0.000000 }, - { 731, 731, 0, 0, 1153, 1153,0.000000 }, - { 732, 732, 0, 0, 40000, 1113,0.000000 }, - { 733, 733, 0, 0, 40000, 613,0.000000 }, - { 734, 734, 0, 0, 4453, 4453,0.000000 }, - { 735, 735, 0, 0, 160, 160,0.000000 }, - { 736, 736, 0, 0, 80, 80,0.000000 }, - { 737, 737, 0, 0, 1513, 13,0.000000 }, - { 738, 738, 38, 0, 33, 33,0.000000 }, - { 739, 739, 44, 0, 40, 40,0.000000 }, - { 500, 500, 58, 0, 13, 13,0.000000 }, - { 740, 740, 24, 0, 160, 160,0.000000 }, - { 741, 741, 60, 0, 133, 133,0.000000 }, - { 736, 736, 44, 0, 80, 80,0.000000 }, - { 742, 742, 25, 0, 146, 146,0.000000 }, - { 743, 743, 60, 0, 33, 33,0.000000 }, - { 742, 742, 30, 0, 146, 146,0.000000 }, - { 377, 377, 60, 0, 93, 93,0.000000 }, - { 742, 742, 33, 0, 173, 173,0.000000 }, - { 744, 744, 60, 0, 53, 53,0.000000 }, - { 742, 742, 35, 0, 186, 186,0.000000 }, - { 742, 742, 37, 0, 200, 200,0.000000 }, - { 745, 745, 0, 0, 313, 313,0.000000 }, - { 742, 742, 40, 0, 206, 206,0.000000 }, - { 746, 746,102, 0, 300, 300,0.000000 }, - { 747, 747, 80, 0, 433, 433,0.000000 }, - { 377, 377, 0, 0, 86, 86,0.000000 }, - { 748, 748, 56, 0, 13, 13,0.000000 }, - { 749, 749, 0, 0, 140, 140,0.000000 }, - { 746, 746,100, 0, 280, 280,0.000000 }, - { 750, 750, 40, 0, 200, 200,0.000000 }, - { 750, 750, 35, 0, 200, 200,0.000000 }, - { 751, 751, 29, 0, 53, 53,0.000000 }, - { 750, 750, 29, 0, 200, 200,0.000000 }, - { 750, 750, 22, 0, 206, 206,0.000000 }, - { 500, 500, 0, 0, 13, 13,0.000000 }, - { 752, 752, 0, 0, 46, 46,0.000000 }, - { 753, 753, 84, 0, 86, 86,0.000000 }, - { 754, 754, 84, 0, 506, 506,0.000000 }, - { 755, 755, 0, 0, 160, 160,0.000000 }, - { 755, 755, 71, 0, 133, 133,0.000000 }, - { 755, 755, 53, 0, 160, 160,0.000000 }, - { 755, 755, 48, 0, 160, 160,0.000000 }, - { 756, 756, 95, 0, 200, 200,0.000000 }, - { 757, 757, 95, 0, 613, 613,0.000000 }, - { 758, 758, 0, 0, 866, 866,0.000000 }, - { 759, 759, 0, 0, 933, 933,0.000000 }, - { 760, 760, 0, 0, 2393, 2393,0.000000 }, - { 761, 761, 0, 0, 760, 760,0.000000 }, - { 762, 762, 0, 0, 1740, 1740,0.000000 }, - { 763, 763, 0, 0, 1846, 1846,0.000000 }, - { 764, 764, 0, 0, 2106, 2106,0.000000 }, - { 765, 765, 0, 0, 1193, 1193,0.000000 }, - { 766, 766, 0, 0, 1613, 1613,0.000000 }, - { 767, 767, 0, 0, 673, 673,0.000000 }, - { 768, 768, 0, 0, 280, 280,0.000000 }, - { 769, 769, 0, 0, 1740, 1740,0.000000 }, - { 770, 770, 0, 0, 193, 193,0.000000 }, - { 771, 771, 0, 0, 140, 140,0.000000 }, - { 772, 772, 0, 0, 933, 933,0.000000 }, - { 773, 773, 0, 0, 333, 333,0.000000 }, - { 774, 774, 0, 0, 40000, 6,0.000000 }, - { 775, 775, 0, 0, 40000, 6,0.000000 }, - { 776, 776, 0, 0, 613, 13,0.000000 }, - { 777, 777, 0, 0, 40000, 80,0.000000 }, - { 778, 778, 0, 0, 40000, 26,0.000000 }, - { 779, 779, 0, 0, 40000, 20,0.000000 }, - { 780, 780, 0, 0, 40000, 20,0.000000 }, - { 781, 781, 0, 0, 40000, 66,0.000000 }, - { 782, 782, 0, 0, 940, 940,0.000000 }, - { 783, 783, 0, 0, 566, 566,0.000000 }, - { 784, 784, 0, 0, 1846, 1846,0.000000 }, - { 785, 785, 0, 0, 1120, 1120,0.000000 }, - { 786, 786, 0, 0, 300, 300,0.000000 }, - { 787, 787, 0, 0, 3000, 3000,0.000000 }, - { 788, 788, 0, 0, 3773, 3773,0.000000 }, - { 789, 789, 0, 0, 620, 620,0.000000 }, - { 790, 790, 0, 0, 846, 846,0.000000 }, - { 791, 791, 0, 0, 4846, 4846,0.000000 }, - { 792, 792, 0, 0, 1133, 1133,0.000000 }, - { 793, 793, 0, 0, 1446, 1446,0.000000 }, - { 794, 794, 0, 0, 566, 566,0.000000 }, - { 795, 795, 0, 0, 600, 600,0.000000 }, - { 796, 796, 0, 0, 1180, 1180,0.000000 }, - { 797, 797, 0, 0, 893, 893,0.000000 }, - { 798, 798, 0, 0, 40000, 20,0.000000 }, - { 799, 799, 0, 0, 40000, 20,0.000000 }, - { 800, 800, 0, 0, 166, 40,0.000000 }, - { 801, 801, 0, 0, 2286, 2286,0.000000 }, - { 802, 802, 0, 0, 40000, 86,0.000000 }, - { 803, 803, 0, 0, 120, 120,0.000000 }, - { 804, 804, 0, 0, 440, 440,0.000000 }, - { 805, 805, 0, 0, 286, 286,0.000000 }, - { 806, 806, 0, 0, 40000, 86,0.000000 }, - { 807, 807, 0, 0, 5473, 120,0.000000 }, - { 808, 808, 0, 0, 100, 13,0.000000 }, - { 809, 809, 0, 0, 40000, 53,0.000000 }, - { 810, 810, 0, 0, 1640, 6,0.000000 }, - { 811, 811, 0, 0, 40000, 53,0.000000 }, - { 812, 812, 0, 0, 1026, 13,0.000000 }, - { 813, 813, 0, 0, 186, 186,0.000000 }, - { 814, 814, 0, 0, 40, 40,0.000000 }, - { 815, 815, 0, 0, 40000, 20,0.000000 }, - { 816, 816, 0, 0, 40000, 20,0.000000 }, - { 817, 817, 0, 0, 873, 873,0.000000 }, - { 818, 818, 0, 0, 4440, 4440,0.000000 }, - { 819, 819, 0, 0, 273, 6,0.000000 }, - { 820, 820, 0, 0, 40000, 53,0.000000 }, - { 821, 821, 0, 0, 40000, 106,0.000000 }, - { 822, 822, 0, 0, 40000, 6,0.000000 }, - { 823, 823, 0, 0, 40000, 0,0.000000 }, - { 824, 824, 0, 0, 40000, 13,0.000000 }, - { 825, 825, 0, 0, 40000, 33,0.000000 }, - { 826, 826, 0, 0, 40000, 20,0.000000 }, - { 827, 827, 0, 0, 40000, 6,0.000000 }, - { 828, 828, 0, 0, 40000, 6,0.000000 }, - { 829, 829, 0, 0, 40000, 20,0.000000 }, - { 830, 830, 0, 0, 40000, 20,0.000000 }, - { 831, 831, 0, 0, 40000, 6,0.000000 }, - { 832, 832, 0, 0, 40000, 13,0.000000 }, - { 833, 833, 0, 0, 40000, 20,0.000000 }, - { 834, 834, 0, 0, 40000, 20,0.000000 }, - { 835, 835, 0, 0, 40000, 20,0.000000 }, - { 836, 836, 0, 0, 40000, 33,0.000000 }, - { 837, 837, 0, 0, 40000, 53,0.000000 }, - { 838, 838, 0, 0, 40000, 6,0.000000 }, - { 839, 839, 0, 0, 1153, 1153,0.000000 }, - { 840, 840, 0, 0, 40000, 20,0.000000 }, - { 841, 841, 0, 0, 20, 20,0.000000 }, - { 842, 842, 0, 0, 2040, 2040,0.000000 }, - { 843, 843, 0, 0, 40000, 6,0.000000 }, - { 844, 844, 0, 0, 40000, 13,0.000000 }, - { 845, 845, 0, 0, 1153, 1153,0.000000 }, - { 846, 846, 0, 0, 1526, 80,0.000000 }, - { 847, 847, 0, 0, 40000, 180,0.000000 }, - { 848, 848, 0, 0, 40000, 86,0.000000 }, - { 849, 849, 0, 0, 40000, 26,0.000000 }, - { 850, 850, 0, 0, 40000, 53,0.000000 }, - { 851, 851, 0, 0, 2886, 2886,0.000000 }, - { 852, 852, 0, 0, 40000, 73,0.000000 }, - { 853, 853, 0, 0, 40000, 126,0.000000 }, - { 854, 854, 0, 0, 1706, 1706,0.000000 }, - { 855, 855, 0, 0, 40000, 213,0.000000 }, - { 856, 856, 0, 0, 920, 920,0.000000 }, - { 857, 857, 0, 0, 993, 993,0.000000 }, - { 858, 858, 0, 0, 1613, 1613,0.000000 }, - { 859, 859, 0, 0, 1000, 106,0.000000 }, - { 860, 860, 0, 0, 40000, 20,0.000000 }, - { 861, 861, 0, 0, 40000, 213,0.000000 }, - { 862, 862, 0, 0, 766, 766,0.000000 }, - { 863, 863, 0, 0, 153, 153,0.000000 }, - { 864, 864, 0, 0, 626, 626,0.000000 }, - { 865, 865, 0, 0, 506, 506,0.000000 }, - { 866, 866, 0, 0, 300, 300,0.000000 }, - { 867, 867, 0, 0, 40000, 33,0.000000 }, - { 868, 868, 0, 0, 40000, 33,0.000000 }, - { 869, 869, 0, 0, 40000, 20,0.000000 }, - { 870, 870, 0, 0, 2106, 2106,0.000000 }, - { 871, 871, 0, 0, 93, 93,0.000000 }, - { 872, 872, 0, 0, 213, 213,0.000000 }, - { 361, 361, 0, 0, 80, 80,0.000000 }, - { 873, 873, 0, 0, 100, 100,0.000000 }, - { 874, 874, 0, 0, 80, 80,0.000000 }, - { 875, 875, 0, 0, 300, 300,0.000000 }, - { 876, 876, 0, 0, 3186, 3186,0.000000 }, - { 877, 877, 0, 0, 226, 226,0.000000 }, - { 878, 878, 0, 0, 53, 53,0.000000 }, - { 879, 879, 0, 0, 2833, 2833,0.000000 }, - { 880, 880, 0, 0, 113, 113,0.000000 }, - { 881, 881, 0, 0, 40000, 40,0.000000 }, - { 882, 882, 0, 0, 40000, 300,0.000000 }, - { 883, 883, 0, 0, 2793, 2793,0.000000 }, - { 884, 884, 36, 0, 73, 73,0.000000 }, - { 885, 885, 48, 0, 60, 60,0.000000 }, - { 885, 885, 36, 0, 73, 73,0.000000 }, - { 886, 886, 36, 0, 20, 20,0.000000 }, - { 887, 887, 32, 0, 46, 46,0.000000 }, - { 767, 767, 96, 0, 580, 580,0.000000 }, - { 888, 888, 30, 0, 53, 53,0.000000 }, - { 889, 889, 35, 0, 106, 106,0.000000 }, - { 890, 890, 60, 0, 86, 86,0.000000 }, - { 884, 884, 59, 0, 40, 40,0.000000 }, - { 890, 890, 44, 0, 80, 80,0.000000 }, - { 891, 891, 41, 0, 166, 166,0.000000 }, - { 892, 892, 47, 0, 40, 40,0.000000 }, - { 891, 891, 44, 0, 140, 140,0.000000 }, - { 891, 891, 48, 0, 153, 153,0.000000 }, - { 893, 893, 62, 0, 606, 606,0.000000 }, - { 891, 891, 51, 0, 160, 160,0.000000 }, - { 891, 891, 54, 0, 160, 160,0.000000 }, - { 894, 894, 40, 0, 386, 386,0.000000 }, - { 891, 891, 57, 0, 113, 113,0.000000 }, - { 895, 895, 97, 0, 73, 73,0.000000 }, - { 896, 896, 50, 0, 86, 86,0.000000 }, - { 376, 376, 60, 0, 153, 153,0.000000 }, - { 897, 897, 53, 0, 33, 33,0.000000 }, - { 898, 898, 46, 0, 53, 53,0.000000 }, - { 897, 897, 57, 0, 33, 33,0.000000 }, - { 899, 899, 42, 0, 193, 193,0.000000 }, - { 899, 899, 37, 0, 200, 200,0.000000 }, - { 900, 900, 41, 0, 200, 200,0.000000 }, - { 900, 900, 37, 0, 193, 193,0.000000 }, - { 871, 871, 77, 0, 46, 46,0.000000 }, - { 871, 871, 72, 0, 40, 40,0.000000 }, - { 388, 388, 70, 0, 46, 46,0.000000 }, - { 901, 901, 39, 0, 173, 173,0.000000 }, - { 902, 902, 36, 0, 1006, 1006,0.000000 }, - { 903, 903, 46, 0, 33, 33,0.000000 }, - { 904, 904, 48, 0, 680, 680,0.000000 }, - { 905, 905, 85, 0, 33, 33,0.000000 }, - { 361, 361, 66, 0, 60, 60,0.000000 }, - { 906, 906, 41, 0, 106, 106,0.000000 }, - { 907, 907, 41, 0, 93, 93,0.000000 }, - { 908, 908, 81, 0, 33, 33,0.000000 }, - { 400, 400, 10, 0, 313, 313,0.000000 }, - { 886, 886, 60, 0, 13, 13,0.000000 }, - { 873, 873, 53, 0, 166, 166,0.000000 }, - { 909, 909, 0, 0, 566, 566,0.000000 }, - { 910, 910, 0, 0, 1313, 1313,0.000000 }, - { 911, 911, 0, 0, 760, 760,0.000000 }, - { 912, 912, 0, 0, 760, 760,0.000000 }, - { 913, 913, 0, 0, 1740, 1740,0.000000 }, - { 914, 914, 0, 0, 1900, 1900,0.000000 }, - { 915, 915, 0, 0, 1173, 1173,0.000000 }, - { 916, 916, 0, 0, 1233, 1233,0.000000 }, - { 917, 917, 0, 0, 493, 493,0.000000 }, - { 362, 362, 0, 0, 246, 246,0.000000 }, - { 918, 918, 0, 0, 226, 226,0.000000 }, - { 919, 919, 0, 0, 1740, 1740,0.000000 }, - { 920, 920, 0, 0, 246, 246,0.000000 }, - { 921, 921, 0, 0, 120, 120,0.000000 }, - { 922, 922, 0, 0, 606, 606,0.000000 }, - { 923, 923, 0, 0, 333, 333,0.000000 }, - { 924, 924, 0, 0, 40000, 6,0.000000 }, - { 925, 925, 0, 0, 40000, 6,0.000000 }, - { 926, 926, 0, 0, 13, 13,0.000000 }, - { 927, 927, 0, 0, 40000, 66,0.000000 }, - { 928, 928, 0, 0, 40000, 26,0.000000 }, - { 929, 929, 0, 0, 40000, 20,0.000000 }, - { 930, 930, 0, 0, 40000, 20,0.000000 }, - { 931, 931, 0, 0, 40000, 33,0.000000 }, - { 932, 932, 0, 0, 866, 866,0.000000 }, - { 933, 933, 0, 0, 566, 566,0.000000 }, - { 934, 934, 0, 0, 1900, 1900,0.000000 }, - { 935, 935, 0, 0, 1146, 1146,0.000000 }, - { 936, 936, 0, 0, 606, 606,0.000000 }, - { 937, 937, 0, 0, 4673, 4673,0.000000 }, - { 938, 938, 0, 0, 3126, 3126,0.000000 }, - { 939, 939, 0, 0, 2406, 2406,0.000000 }, - { 940, 940, 0, 0, 440, 440,0.000000 }, - { 941, 941, 0, 0, 3200, 3200,0.000000 }, - { 942, 942, 0, 0, 1000, 1000,0.000000 }, - { 943, 943, 0, 0, 593, 593,0.000000 }, - { 944, 944, 0, 0, 546, 546,0.000000 }, - { 945, 945, 0, 0, 620, 620,0.000000 }, - { 946, 946, 0, 0, 1206, 1206,0.000000 }, - { 947, 947, 0, 0, 680, 680,0.000000 }, - { 948, 948, 0, 0, 40000, 20,0.000000 }, - { 949, 949, 0, 0, 40000, 20,0.000000 }, - { 950, 950, 0, 0, 4793, 33,0.000000 }, - { 951, 951, 0, 0, 1773, 1773,0.000000 }, - { 952, 952, 0, 0, 40000, 86,0.000000 }, - { 953, 953, 0, 0, 173, 173,0.000000 }, - { 954, 954, 0, 0, 406, 406,0.000000 }, - { 955, 955, 0, 0, 280, 280,0.000000 }, - { 956, 956, 0, 0, 5453, 33,0.000000 }, - { 957, 957, 0, 0, 2466, 100,0.000000 }, - { 958, 958, 0, 0, 973, 973,0.000000 }, - { 959, 959, 0, 0, 40000, 53,0.000000 }, - { 960, 960, 0, 0, 40000, 33,0.000000 }, - { 961, 961, 0, 0, 1026, 13,0.000000 }, - { 962, 962, 0, 0, 166, 166,0.000000 }, - { 963, 963, 0, 0, 806, 806,0.000000 }, - { 964, 964, 0, 0, 40000, 20,0.000000 }, - { 965, 965, 0, 0, 60, 20,0.000000 }, - { 966, 966, 0, 0, 1020, 1020,0.000000 }, - { 967, 967, 0, 0, 3426, 3426,0.000000 }, - { 968, 968, 0, 0, 40000, 20,0.000000 }, - { 969, 969, 0, 0, 40000, 20,0.000000 }, - { 970, 970, 0, 0, 40000, 106,0.000000 }, - { 971, 971, 0, 0, 40000, 6,0.000000 }, - { 972, 972, 0, 0, 40000, 0,0.000000 }, - { 973, 973, 0, 0, 2280, 2280,0.000000 }, - { 974, 974, 0, 0, 40000, 20,0.000000 }, - { 975, 975, 0, 0, 40000, 6,0.000000 }, - { 976, 976, 0, 0, 40000, 6,0.000000 }, - { 977, 977, 0, 0, 40000, 0,0.000000 }, - { 978, 978, 0, 0, 40000, 6,0.000000 }, - { 979, 979, 0, 0, 40000, 33,0.000000 }, - { 980, 980, 0, 0, 40000, 0,0.000000 }, - { 981, 981, 0, 0, 40000, 13,0.000000 }, - { 982, 982, 0, 0, 40000, 20,0.000000 }, - { 983, 983, 0, 0, 40000, 33,0.000000 }, - { 984, 984, 0, 0, 40000, 20,0.000000 }, - { 985, 985, 0, 0, 40000, 33,0.000000 }, - { 986, 986, 0, 0, 40000, 20,0.000000 }, - { 987, 987, 0, 0, 40000, 6,0.000000 }, - { 988, 988, 0, 0, 1133, 1133,0.000000 }, - { 989, 989, 0, 0, 40000, 20,0.000000 }, - { 990, 990, 0, 0, 1340, 1340,0.000000 }, - { 991, 991, 0, 0, 3533, 3533,0.000000 }, - { 992, 992, 0, 0, 40000, 6,0.000000 }, - { 993, 993, 0, 0, 40000, 26,0.000000 }, - { 994, 994, 0, 0, 4140, 4140,0.000000 }, - { 995, 995, 0, 0, 1206, 1206,0.000000 }, - { 996, 996, 0, 0, 40000, 173,0.000000 }, - { 997, 997, 0, 0, 380, 80,0.000000 }, - { 998, 998, 0, 0, 40000, 26,0.000000 }, - { 999, 999, 0, 0, 40000, 20,0.000000 }, - {1000,1000, 0, 0, 2893, 2893,0.000000 }, - {1001,1001, 0, 0, 40000, 73,0.000000 }, - {1002,1002, 0, 0, 40000, 126,0.000000 }, - {1003,1003, 0, 0, 4373, 4373,0.000000 }, - {1004,1004, 0, 0, 40000, 240,0.000000 }, - {1005,1005, 0, 0, 993, 993,0.000000 }, - {1006,1006, 0, 0, 760, 760,0.000000 }, - {1007,1007, 0, 0, 1380, 1380,0.000000 }, - {1008,1008, 0, 0, 726, 53,0.000000 }, - {1009,1009, 0, 0, 40000, 33,0.000000 }, - {1010,1010, 0, 0, 40000, 213,0.000000 }, - {1011,1011, 0, 0, 1046, 1046,0.000000 }, - {1012,1012, 0, 0, 273, 273,0.000000 }, - {1013,1013, 0, 0, 626, 626,0.000000 }, - {1014,1014, 0, 0, 1166, 1166,0.000000 }, - {1015,1015, 0, 0, 153, 153,0.000000 }, - {1016,1016, 0, 0, 40000, 6,0.000000 }, - {1017,1017, 0, 0, 40000, 33,0.000000 }, - {1018,1018, 0, 0, 40000, 20,0.000000 }, - {1019,1019, 0, 0, 2106, 2106,0.000000 }, - { 444, 444, 0, 0, 86, 86,0.000000 }, - {1020,1020, 0, 0, 180, 180,0.000000 }, - { 449, 449, 0, 0, 80, 80,0.000000 }, - { 453, 453, 0, 0, 20, 20,0.000000 }, - {1021,1021, 0, 0, 20, 20,0.000000 }, - {1022,1022, 0, 0, 246, 246,0.000000 }, - {1023,1023, 0, 0, 3186, 3186,0.000000 }, - {1024,1024, 0, 0, 226, 226,0.000000 }, - {1025,1025, 0, 0, 186, 186,0.000000 }, - {1026,1026, 0, 0, 2833, 2833,0.000000 }, - {1027,1027, 0, 0, 2460, 2460,0.000000 }, - {1028,1028, 0, 0, 40000, 40,0.000000 }, - {1029,1029, 0, 0, 40000, 286,0.000000 }, - {1030,1030, 0, 0, 40000, 146,0.000000 }, - {1031,1031, 0, 0, 586, 586,0.000000 }, - {1032,1032, 32, 0, 46, 46,0.000000 }, - {1033,1033, 30, 0, 26, 26,0.000000 }, - {1034,1034, 96, 0, 40, 40,0.000000 }, - {1035,1035, 60, 0, 186, 186,0.000000 }, - {1036,1036, 0, 0, 1100, 1100,0.000000 }, - {1037,1037, 0, 0, 40000, 33,0.000000 }, - {1038,1038, 0, 0, 1740, 1740,0.000000 }, - {1039,1039, 0, 0, 1793, 1793,0.000000 }, - {1040,1040, 0, 0, 160, 160,0.000000 }, - {1041,1041, 0, 0, 1206, 1206,0.000000 }, - {1042,1042, 0, 0, 353, 353,0.000000 }, - {1043,1043, 0, 0, 40000, 6,0.000000 }, - {1044,1044, 0, 0, 40000, 0,0.000000 }, - {1045,1045, 0, 0, 40000, 20,0.000000 }, - {1046,1046, 0, 0, 1186, 1186,0.000000 }, - {1047,1047, 0, 0, 1093, 1093,0.000000 }, - {1048,1048, 0, 0, 620, 620,0.000000 }, - {1049,1049, 0, 0, 4440, 4440,0.000000 }, - {1050,1050, 0, 0, 4506, 4506,0.000000 }, - {1051,1051, 0, 0, 4673, 4673,0.000000 }, - {1052,1052, 0, 0, 2386, 2386,0.000000 }, - {1053,1053, 0, 0, 40000, 146,0.000000 }, - {1054,1054, 0, 0, 1180, 1180,0.000000 }, - {1055,1055, 0, 0, 320, 320,0.000000 }, - {1056,1056, 0, 0, 633, 633,0.000000 }, - {1057,1057, 0, 0, 80, 80,0.000000 }, - {1058,1058, 0, 0, 1180, 1180,0.000000 }, - {1059,1059, 0, 0, 6120, 100,0.000000 }, - {1060,1060, 0, 0, 86, 86,0.000000 }, - {1061,1061, 0, 0, 206, 206,0.000000 }, - {1062,1062, 0, 0, 40000, 86,0.000000 }, - {1063,1063, 0, 0, 40000, 266,0.000000 }, - {1064,1064, 0, 0, 806, 806,0.000000 }, - {1065,1065, 0, 0, 40000, 20,0.000000 }, - {1066,1066, 0, 0, 40000, 53,0.000000 }, - {1067,1067, 0, 0, 40000, 53,0.000000 }, - {1068,1068, 0, 0, 40000, 26,0.000000 }, - {1069,1069, 0, 0, 40000, 20,0.000000 }, - {1070,1070, 0, 0, 40000, 20,0.000000 }, - {1071,1071, 0, 0, 40000, 6,0.000000 }, - {1072,1072, 0, 0, 40000, 26,0.000000 }, - {1073,1073, 0, 0, 40000, 13,0.000000 }, - {1074,1074, 0, 0, 40000, 60,0.000000 }, - {1075,1075, 0, 0, 213, 213,0.000000 }, - {1076,1076, 0, 0, 40000, 73,0.000000 }, - {1077,1077, 0, 0, 4513, 4513,0.000000 }, - {1078,1078, 0, 0, 313, 313,0.000000 }, - {1079,1079, 0, 0, 4273, 4273,0.000000 }, - {1080,1080, 0, 0, 40000, 26,0.000000 }, - {1081,1081, 0, 0, 3153, 3153,0.000000 }, - {1082,1082, 0, 0, 40000, 180,0.000000 }, - {1083,1083, 0, 0, 40000, 213,0.000000 }, - {1084,1084, 0, 0, 1740, 13,0.000000 }, - {1085,1085, 0, 0, 2853, 2853,0.000000 }, - {1086,1086, 0, 0, 40000, 213,0.000000 }, - {1087,1087, 0, 0, 3946, 3946,0.000000 }, - {1088,1088, 0, 0, 2253, 2253,0.000000 }, - {1089,1089, 0, 0, 40000, 260,0.000000 }, - {1090,1090, 0, 0, 166, 166,0.000000 }, - {1091,1091, 0, 0, 40000, 493,0.000000 }, - {1092,1092, 0, 0, 2126, 2126,0.000000 }, - {1093,1093, 0, 0, 40000, 480,0.000000 }, - {1094,1094, 0, 0, 40000, 213,0.000000 }, - {1095,1095, 0, 0, 146, 146,0.000000 }, - {1096,1096, 0, 0, 333, 333,0.000000 }, - {1097,1097, 0, 0, 466, 466,0.000000 }, - {1098,1098, 0, 0, 40000, 40,0.000000 }, - {1099,1099, 0, 0, 4926, 4926,0.000000 }, - {1100,1100, 0, 0, 5113, 5113,0.000000 }, - {1101,1101, 0, 0, 3060, 13,0.000000 }, - {1102,1102, 0, 0, 420, 420,0.000000 }, - {1103,1103, 0, 0, 300, 300,0.000000 }, - {1104,1104, 0, 0, 4426, 4426,0.000000 }, - {1105,1105, 0, 0, 5513, 5513,0.000000 }, - {1106,1106, 0, 0, 40000, 233,0.000000 }, - { 430, 430, 0, 0, 300, 300,0.000000 }, - {1107,1107, 35, 0, 73, 73,0.000000 }, - {1090,1090, 77, 0, 80, 80,0.000000 }, - {1090,1090, 72, 0, 80, 80,0.000000 }, - {1108,1108, 0, 0, 60, 60,0.000000 }, - {1109,1109, 0, 0, 1453, 1453,0.000000 }, - {1110,1111, 0, 1, 506, 506,0.000000 }, - {1112,1113, 0, 1, 1253, 1253,0.031250 }, - {1114,1114, 0, 0, 866, 866,0.000000 }, - {1115,1116, 0, 1, 1473, 1473,0.000000 }, - {1117,1117, 0, 0, 1600, 1600,0.000000 }, - {1118,1118, 0, 0, 680, 680,0.000000 }, - {1119,1119, 0, 0, 1133, 1133,0.000000 }, - {1120,1120, 0, 0, 1013, 1013,0.000000 }, - {1121,1121, 0, 0, 860, 860,0.000000 }, - {1122,1122, 0, 0, 1473, 1473,0.000000 }, - {1123,1123, 0, 0, 280, 280,0.000000 }, - {1124,1124, 0, 0, 53, 53,0.000000 }, - {1125,1125, 0, 0, 1260, 1260,0.000000 }, - {1126,1126, 0, 0, 906, 906,0.000000 }, - {1127,1127, 0, 0, 40000, 66,0.000000 }, - {1128,1128, 0, 0, 260, 13,0.000000 }, - {1129,1130, 0, 1, 13973, 13,0.156250 }, - {1131,1131, 0, 0, 40000, 173,0.000000 }, - {1132,1132, 0, 0, 40000, 53,0.000000 }, - {1133,1134, 0, 1, 40000, 20,-0.046875 }, - {1135,1135, 0, 0, 40000, 26,0.000000 }, - {1136,1137, 0, 1, 40000, 113,0.000025 }, - {1138,1138, 0, 0, 3366, 3366,0.000000 }, - {1139,1139, 0, 0, 400, 400,0.000000 }, - {1140,1140, 0, 0, 473, 473,0.000000 }, - {1141,1141, 0, 0, 840, 840,0.000000 }, - {1142,1142, 0, 0, 800, 800,0.000000 }, - {1143,1143, 0, 0, 2173, 0,0.000000 }, - {1144,1144, 0, 0, 40000, 0,0.000000 }, - {1145,1145, 0, 0, 1433, 1433,0.000000 }, - {1146,1146, 0, 0, 386, 386,0.000000 }, - {1147,1147, 0, 0, 1253, 1253,0.000000 }, - {1148,1148, 0, 0, 1606, 1606,0.000000 }, - {1149,1150, 0, 1, 1553, 1553,-0.031250 }, - {1151,1151, 0, 0, 40000, 6,0.000000 }, - {1152,1152, 0, 0, 1560, 1560,0.000000 }, - {1153,1153, 0, 0, 386, 386,0.000000 }, - {1154,1154, 0, 1, 40000, 20,-0.156250 }, - {1155,1155, 0, 0, 3886, 6,0.000000 }, - {1156,1156, 0, 0, 40000, 66,0.000000 }, - {1157,1157, 0, 0, 40000, 60,0.000000 }, - {1158,1158, 0, 0, 40000, 266,0.000000 }, - {1159,1160, 0, 1, 40000, 273,0.171875 }, - {1161,1161, 0, 0, 173, 173,0.000000 }, - {1162,1162, 0, 0, 993, 993,0.000000 }, - {1163,1163, 0, 0, 726, 726,0.000000 }, - {1164,1165, 0, 1, 40000, 206,-0.125000 }, - {1166,1167, 0, 1, 40000, 266,0.078125 }, - {1168,1168, 0, 1, 40000, 1073,-0.078125 }, - {1169,1170, 0, 1, 40000, 253,0.062500 }, - {1171,1172, 0, 1, 40000, 533,0.156250 }, - {1173,1173, 0, 0, 1813, 1813,0.000000 }, - {1174,1174, 0, 0, 40000, 200,0.000000 }, - {1175,1176, 0, 1, 360, 360,0.000000 }, - {1177,1177, 0, 0, 40000, 6,0.000000 }, - {1178,1178, 0, 0, 806, 6,0.000000 }, - {1179,1179, 0, 0, 1600, 1600,0.000000 }, - {1180,1180, 0, 0, 60, 60,0.000000 }, - {1181,1182, 0, 1, 3153, 3153,0.000025 }, - {1183,1184, 0, 1, 826, 6,0.046875 }, - {1185,1186, 0, 1, 3106, 3106,0.093750 }, - {1187,1188, 0, 1, 1020, 1020,0.093750 }, - {1189,1189, 0, 0, 40000, 33,0.000000 }, - {1190,1190, 0, 0, 40000, 20,0.000000 }, - {1191,1191, 0, 0, 40000, 0,0.000000 }, - {1192,1192, 0, 0, 266, 6,0.000000 }, - {1193,1193, 0, 0, 40000, 33,0.000000 }, - {1194,1194, 0, 0, 40000, 26,0.000000 }, - {1195,1195, 0, 0, 40000, 0,0.000000 }, - {1196,1196, 0, 0, 40000, 13,0.000000 }, - {1197,1197, 0, 0, 40000, 0,0.000000 }, - {1198,1198, 0, 0, 40000, 6,0.000000 }, - {1199,1199, 0, 0, 40000, 53,0.000000 }, - {1200,1200, 0, 0, 40000, 20,0.000000 }, - {1201,1201, 0, 0, 40000, 20,0.000000 }, - {1202,1202, 0, 0, 140, 140,0.000000 }, - {1203,1203, 0, 0, 40000, 93,0.000000 }, - {1204,1204, 0, 0, 40000, 6,0.000000 }, - {1205,1206, 0, 1, 40000, 86,0.031250 }, - {1207,1208, 0, 1, 40000, 100,-0.000025 }, - {1209,1209, 0, 0, 40000, 53,0.000000 }, - {1210,1211, 0, 1, 40000, 0,0.031250 }, - {1212,1212, 0, 0, 40000, 0,0.000000 }, - {1213,1214, 0, 1, 40000, 320,-0.093750 }, - {1215,1216, 0, 1, 1660, 80,-0.046875 }, - {1217,1217, 0, 0, 40000, 66,0.000000 }, - {1218,1219, 0, 1, 40000, 233,0.031250 }, - {1220,1220, 0, 1, 1960, 1960,0.031250 }, - {1221,1222, 0, 1, 17500, 46,0.171875 }, - {1223,1223, 0, 0, 2273, 2273,0.000000 }, - {1224,1224, 0, 0, 1933, 1933,0.000000 }, - {1225,1150, 0, 1, 3126, 13,-0.031250 }, - {1226,1226, 0, 0, 40000, 640,0.000000 }, - {1227,1227, 0, 0, 1080, 1080,0.000000 }, - {1228,1229, 0, 1, 40000, 33,0.125000 }, - {1230,1230, 0, 0, 1046, 1046,0.000000 }, - {1231,1232, 0, 1, 1553, 1553,-0.031250 }, - {1233,1234, 0, 1, 2066, 2066,-0.187500 }, - {1235,1235, 0, 0, 40000, 466,0.000000 }, - {1236,1236, 0, 0, 400, 400,0.000000 }, - {1237,1237, 0, 0, 2706, 2706,0.000000 }, - {1238,1238, 0, 0, 1220, 1220,0.000000 }, - {1239,1239, 0, 0, 446, 446,0.000000 }, - {1240,1241, 0, 1, 360, 360,0.000000 }, - {1242,1242, 0, 0, 4806, 4806,0.000000 }, - {1243,1243, 0, 0, 80, 80,0.000000 }, - {1244,1244, 0, 0, 40000, 80,0.000000 }, - {1245,1245, 0, 0, 40000, 86,0.000000 }, - {1246,1246, 0, 0, 40000, 40,0.000000 }, - {1247,1247, 0, 0, 1920, 1920,0.000000 }, - {1248,1248, 0, 0, 66, 66,0.000000 }, - {1249,1249, 0, 0, 40000, 233,0.000000 }, - {1250,1250, 0, 0, 113, 113,0.000000 }, - {1251,1251, 0, 0, 46, 46,0.000000 }, - {1252,1252, 0, 0, 140, 140,0.000000 }, - {1253,1253, 0, 0, 886, 886,0.000000 }, - {1254,1254, 0, 0, 1080, 1080,0.000000 }, - {1255,1255, 0, 0, 206, 206,0.000000 }, - {1256,1256, 0, 0, 280, 280,0.000000 }, - {1257,1257, 0, 0, 2873, 2873,0.000000 }, - {1258,1258, 0, 0, 313, 313,0.000000 }, - {1259,1259, 0, 0, 40000, 73,0.000000 }, - {1260,1260, 29, 0, 1320, 1320,0.000000 }, - {1261,1261, 65, 0, 40000, 1746,0.000000 }, - {1262,1262, 0, 0, 153, 153,0.000000 }, - {1263,1263, 25, 0, 33, 33,0.000000 }, - {1264,1264, 83, 0, 53, 53,0.000000 }, - {1265,1265, 32, 0, 40, 40,0.000000 }, - {1266,1266, 60, 0, 46, 46,0.000000 }, - {1267,1267, 36, 0, 46, 46,0.000000 }, - {1268,1268, 27, 0, 13, 13,0.000000 }, - {1269,1269, 31, 0, 266, 266,0.000000 }, - {1270,1270, 21, 0, 246, 246,0.000000 }, - {1270,1270, 26, 0, 253, 253,0.000000 }, - {1270,1270, 28, 0, 260, 260,0.000000 }, - {1271,1271, 60, 0, 280, 280,0.000000 }, - {1270,1270, 32, 0, 206, 206,0.000000 }, - {1272,1272, 60, 0, 260, 260,0.000000 }, - {1273,1273, 96, 0, 140, 140,0.000000 }, - {1274,1274, 72, 0, 133, 133,0.000000 }, - {1275,1275, 79, 0, 46, 46,0.000000 }, - {1276,1276, 69, 0, 126, 126,0.000000 }, - {1277,1277, 71, 0, 146, 146,0.000000 }, - {1278,1278, 22, 0, 566, 566,0.000000 }, - {1279,1279, 55, 0, 66, 66,0.000000 }, - {1279,1279, 48, 0, 80, 80,0.000000 }, - {1280,1280, 0, 0, 6, 6,0.000000 }, - {1281,1281, 49, 0, 6, 6,0.000000 }, - {1282,1282, 73, 0, 60, 60,0.000000 }, - {1282,1282, 68, 0, 60, 60,0.000000 }, - {1282,1282, 61, 0, 80, 80,0.000000 }, - {1283,1283, 0, 0, 6, 6,0.000000 }, - {1284,1284, 0, 0, 40000, 46,0.000000 }, - {1285,1285, 0, 0, 40000, 20,0.000000 }, - {1286,1286, 0, 0, 2380, 2380,0.000000 }, - {1287,1287, 0, 0, 700, 700,0.000000 }, - {1288,1289, 0, 1, 653, 6,0.000000 }, - {1290,1290, 0, 0, 80, 80,0.000000 }, - {1291,1292, 36, 1, 46, 46,0.000000 }, - {1293,1293, 69, 0, 126, 126,0.000000 }, - {1294,1294, 0, 0, 120, 120,0.000000 }, - {1295,1295, 0, 0, 40000, 0,0.000000 }, - {1296,1296, 0, 0, 1173, 1173,0.000000 }, - {1297,1297, 22, 0, 566, 566,0.000000 }, - {1298,1298, 0, 0, 40000, 0,0.000000 }, - {1299,1299, 0, 0, 993, 993,0.000000 }, - {1300,1300, 0, 0, 1900, 1900,0.000000 }, - {1301,1301, 0, 0, 1046, 1046,0.000000 }, - {1302,1302, 0, 0, 293, 293,0.000000 }, - {1303,1303, 0, 0, 40000, 33,0.000000 }, - {1304,1304, 0, 0, 40000, 6,0.000000 }, - {1305,1305, 0, 0, 40000, 20,0.000000 }, - {1306,1306, 0, 0, 40000, 193,0.000000 }, - {1307,1307, 0, 0, 40000, 153,0.000000 }, - {1308,1308, 0, 0, 40000, 6,0.000000 }, - {1309,1309, 0, 0, 40000, 46,0.000000 }, - {1310,1310, 0, 0, 40000, 73,0.000000 }, - {1311,1311, 0, 0, 920, 920,0.000000 }, - {1312,1312, 0, 0, 4580, 4580,0.000000 }, - {1313,1313, 0, 0, 1026, 1026,0.000000 }, - {1314,1314, 0, 0, 40000, 6,0.000000 }, - {1315,1315, 0, 0, 3746, 13,0.000000 }, - {1316,1316, 0, 0, 40000, 233,0.000000 }, - {1317,1317, 0, 0, 40000, 153,0.000000 }, - {1318,1318, 0, 0, 40000, 140,0.000000 }, - {1319,1319, 0, 0, 2620, 2620,0.000000 }, - {1320,1320, 0, 0, 40000, 140,0.000000 }, - {1321,1321, 0, 0, 233, 233,0.000000 }, - {1322,1322, 0, 0, 40000, 6,0.000000 }, - {1323,1323, 0, 0, 40000, 0,0.000000 }, - {1324,1324, 0, 0, 40000, 26,0.000000 }, - {1325,1325, 0, 0, 40000, 6,0.000000 }, - { 260, 260, 0, 0, 40000, 20,0.000000 }, - {1326,1326, 0, 0, 40000, 20,0.000000 }, - {1327,1327, 0, 0, 40000, 0,0.000000 }, - {1328,1328, 0, 0, 40000, 13,0.000000 }, - {1329,1329, 0, 0, 40000, 73,0.000000 }, - {1330,1330, 0, 0, 40000, 53,0.000000 }, - {1331,1331, 0, 0, 40000, 66,0.000000 }, - {1332,1332, 0, 0, 40000, 66,0.000000 }, - {1333,1333, 0, 0, 40000, 6,0.000000 }, - {1334,1334, 0, 0, 40000, 73,0.000000 }, - {1335,1335, 0, 0, 40000, 133,0.000000 }, - {1336,1336, 0, 0, 40000, 233,0.000000 }, - {1337,1337, 0, 0, 40000, 406,0.000000 }, - {1338,1338, 0, 0, 1766, 93,0.000000 }, - {1339,1339, 0, 0, 40000, 533,0.000000 }, - {1340,1340, 0, 0, 40000, 106,0.000000 }, - {1341,1341, 0, 0, 593, 13,0.000000 }, - {1342,1342, 0, 0, 940, 940,0.000000 }, - {1343,1343, 0, 0, 40000, 53,0.000000 }, - {1344,1344, 0, 0, 2006, 2006,0.000000 }, - {1345,1345, 0, 0, 40000, 933,0.000000 }, - {1346,1346, 0, 0, 973, 973,0.000000 }, - { 378, 378, 84, 0, 440, 440,0.000000 }, - {1347,1347, 24, 0, 46, 46,0.000000 }, - {1348,1348, 44, 0, 80, 80,0.000000 }, - {1349,1349, 40, 0, 306, 306,0.000000 }, - {1350,1350, 60, 0, 340, 340,0.000000 }, - {1351,1351, 0, 0, 866, 866,0.000000 }, - {1352,1352, 0, 0, 993, 993,0.000000 }, - {1353,1353, 0, 0, 633, 633,0.000000 }, - {1354,1354, 0, 0, 40000, 40,0.000000 }, - {1355,1355, 0, 0, 973, 973,0.000000 }, - {1356,1356, 0, 0, 40000, 126,0.000000 }, - {1357,1357, 0, 0, 166, 166,0.000000 }, - {1358,1358, 0, 0, 640, 640,0.000000 }, - {1359,1359, 0, 0, 100, 100,0.000000 }, - {1360,1360, 0, 0, 40000, 113,0.000000 }, - {1361,1361, 0, 0, 40000, 240,0.000000 }, - {1362,1362, 0, 0, 3793, 80,0.000000 }, - {1363,1363, 0, 0, 40000, 240,0.000000 }, - {1364,1364, 0, 0, 126, 126,0.000000 }, - {1365,1365, 0, 0, 40000, 20,0.000000 }, - {1366,1366, 0, 0, 40000, 26,0.000000 }, - {1367,1367, 0, 0, 2233, 6,0.000000 }, - {1368,1368, 0, 0, 40000, 53,0.000000 }, - {1369,1369, 0, 0, 40000, 33,0.000000 }, - {1370,1370, 0, 0, 40000, 13,0.000000 }, - {1371,1371, 0, 0, 40000, 13,0.000000 }, - {1372,1372, 0, 0, 40000, 26,0.000000 }, - {1373,1373, 0, 0, 40000, 6,0.000000 }, - {1374,1374, 0, 0, 40000, 13,0.000000 }, - {1375,1375, 0, 0, 4473, 13,0.000000 }, - {1376,1376, 0, 0, 146, 146,0.000000 }, - {1377,1377, 0, 0, 86, 86,0.000000 }, - {1378,1378, 35, 0, 73, 73,0.000000 }, - {1379,1379, 49, 0, 40, 40,0.000000 }, - {1377,1377, 48, 0, 80, 80,0.000000 }, - {1380,1380, 58, 0, 40, 40,0.000000 }, - {1377,1377, 60, 0, 86, 86,0.000000 }, - {1381,1381, 47, 0, 106, 106,0.000000 }, - {1382,1382, 60, 0, 20, 20,0.000000 }, - {1381,1381, 49, 0, 153, 153,0.000000 }, - {1383,1383, 72, 0, 80, 80,0.000000 }, - {1381,1381, 51, 0, 200, 200,0.000000 }, - {1384,1384, 84, 0, 273, 273,0.000000 }, - {1381,1381, 54, 0, 233, 233,0.000000 }, - {1381,1381, 57, 0, 260, 260,0.000000 }, - {1385,1385, 72, 0, 506, 506,0.000000 }, - {1381,1381, 60, 0, 306, 306,0.000000 }, - {1386,1386, 36, 0, 866, 866,0.000000 }, - {1387,1387, 93, 0, 66, 66,0.000000 }, - {1388,1388, 72, 0, 273, 273,0.000000 }, - {1389,1389, 84, 0, 426, 426,0.000000 }, - {1390,1390, 36, 0, 20, 20,0.000000 }, - {1391,1391, 64, 0, 86, 86,0.000000 }, - {1392,1392, 68, 0, 26, 26,0.000000 }, - {1393,1393, 0, 0, 1226, 1226,0.000000 }, - {1394,1394, 0, 0, 40000, 140,0.000000 }, - {1395,1395, 0, 0, 40000, 0,0.000000 }, - {1396,1396, 0, 0, 513, 513,0.000000 }, - {1397,1397, 0, 0, 40000, 126,0.000000 }, - {1398,1398, 0, 0, 320, 320,0.000000 }, - {1399,1399, 0, 0, 40000, 0,0.000000 }, - {1400,1400, 0, 0, 1766, 1766,0.000000 }, - {1401,1401, 0, 0, 2513, 2513,0.000000 }, - {1402,1402, 0, 0, 1300, 1300,0.000000 }, - {1403,1403, 0, 0, 46, 46,0.000000 }, - {1404,1404, 0, 0, 186, 6,0.000000 }, - {1405,1405, 0, 0, 40000, 6,0.000000 }, - {1406,1406, 0, 0, 40, 26,0.000000 }, - {1407,1407, 0, 0, 166, 166,0.000000 }, - {1408,1408, 0, 0, 2193, 2193,0.000000 }, - {1409,1409, 0, 0, 40000, 206,0.000000 }, - {1410,1410, 0, 0, 40000, 1460,0.000000 }, - {1411,1411, 0, 0, 166, 166,0.000000 }, - {1412,1412, 0, 0, 1380, 1380,0.000000 }, - {1413,1413, 0, 0, 533, 533,0.000000 }, - {1414,1414, 0, 0, 40000, 33,0.000000 }, - {1415,1415, 0, 0, 40000, 53,0.000000 }, - {1416,1416, 0, 0, 40000, 0,0.000000 }, - {1417,1417, 0, 0, 40000, 6,0.000000 }, - {1418,1418, 0, 0, 40000, 6,0.000000 }, - {1419,1419, 0, 0, 913, 913,0.000000 }, - {1420,1420, 0, 0, 1233, 6,0.000000 }, - {1421,1421, 0, 0, 126, 126,0.000000 }, - {1422,1422, 0, 0, 40000, 46,0.000000 }, - {1423,1423, 0, 0, 933, 933,0.000000 }, - {1424,1424, 0, 0, 1846, 1846,0.000000 }, - {1425,1425, 0, 0, 973, 973,0.000000 }, - {1426,1426, 0, 0, 160, 160,0.000000 }, - {1427,1427, 0, 0, 40000, 106,0.000000 }, - {1428,1428, 0, 0, 120, 120,0.000000 }, - {1429,1429, 0, 0, 40000, 6,0.000000 }, - {1430,1430, 0, 0, 93, 93,0.000000 }, - {1431,1431, 0, 0, 40, 40,0.000000 }, - {1432,1432, 0, 0, 2420, 2420,0.000000 }, - {1433,1433, 0, 0, 1153, 1153,0.000000 }, - {1434,1434, 0, 0, 2406, 2406,0.000000 }, - { 740, 740, 0, 0, 80, 80,0.000000 }, - {1435,1435, 0, 0, 40000, 3220,0.000000 }, - { 739, 739, 48, 0, 93, 93,0.000000 }, - { 500, 500, 55, 0, 13, 13,0.000000 }, - { 740, 740, 60, 0, 53, 53,0.000000 }, - { 500, 500, 41, 0, 13, 13,0.000000 }, - {1436,1436, 84, 0, 40, 40,0.000000 }, - {1437,1437, 84, 0, 73, 73,0.000000 }, - { 500, 500, 48, 0, 13, 13,0.000000 }, - {1438,1438, 15, 0, 86, 86,0.000000 }, - { 752, 752, 49, 0, 46, 46,0.000000 }, - {1438,1438, 16, 0, 93, 93,0.000000 }, - {1438,1438, 12, 0, 86, 86,0.000000 }, - { 740, 740, 55, 0, 53, 53,0.000000 }, - { 752, 752, 18, 0, 46, 46,0.000000 }, - { 752, 752, 15, 0, 46, 46,0.000000 }, - { 752, 752, 17, 0, 46, 46,0.000000 }, - {1439,1440, 0, 0, 1340, 1340,0.000000 }, - {1441,1442, 0, 0, 1113, 1113,0.000000 }, - {1443,1444, 0, 0, 2133, 2133,0.000000 }, - {1445,1446, 0, 0, 953, 953,0.000000 }, - {1447,1448, 0, 0, 100, 100,0.000000 }, - {1449,1450, 0, 0, 1313, 1313,0.000000 }, - { 181,1451, 0, 0, 473, 473,0.000000 }, - {1452,1453, 0, 0, 680, 680,0.000000 }, - {1454,1455, 0, 0, 260, 260,0.000000 }, - {1456,1457, 0, 0, 193, 193,0.000000 }, - {1458,1459, 0, 0, 1320, 1320,0.000000 }, - { 190,1460, 0, 0, 646, 6,0.000000 }, - { 192,1461, 0, 0, 40000, 6,0.000000 }, - {1462,1463, 0, 0, 40000, 113,0.000000 }, - {1464,1465, 0, 0, 40000, 133,0.000000 }, - {1466,1467, 0, 0, 40000, 6,0.000000 }, - {1468,1469, 0, 0, 40000, 0,0.000000 }, - { 35,1470, 0, 0, 1446, 1446,0.000000 }, - { 36,1471, 0, 0, 1606, 1606,0.000000 }, - {1472,1473, 0, 0, 1553, 1553,0.000000 }, - {1474,1475, 0, 0, 2133, 2133,0.000000 }, - { 39,1476, 0, 0, 40000, 26,0.000000 }, - {1477,1476, 0, 0, 40000, 46,0.000000 }, - {1478,1479, 0, 0, 40000, 240,0.000000 }, - { 50,1480, 0, 0, 40000, 153,0.000000 }, - {1481,1482, 0, 0, 40000, 46,0.000000 }, - {1483,1484, 0, 0, 2300, 2300,0.000000 }, - {1485,1486, 0, 0, 40000, 86,0.000000 }, - { 55,1487, 0, 0, 40000, 20,0.000000 }, - {1488,1489, 0, 0, 40000, 20,0.000000 }, - {1490,1491, 0, 0, 40000, 6,0.000000 }, - {1492,1493, 0, 0, 40000, 0,0.000000 }, - {1494,1495, 0, 0, 40000, 6,0.000000 }, - {1496,1497, 0, 0, 40000, 6,0.000000 }, - {1496,1498, 0, 0, 40000, 6,0.000000 }, - {1499,1500, 0, 0, 40000, 6,0.000000 }, - {1501,1502, 0, 0, 40000, 53,0.000000 }, - {1503,1504, 0, 0, 40000, 33,0.000000 }, - {1505,1506, 0, 0, 40000, 6,0.000000 }, - { 86,1507, 0, 0, 40000, 20,0.000000 }, - {1508,1509, 0, 0, 1766, 1766,0.000000 }, - {1510,1511, 0, 0, 2853, 13,0.000000 }, - {1512,1513, 0, 0, 593, 593,0.000000 }, - {1514,1515, 0, 0, 1126, 33,0.000000 }, - {1516,1517, 0, 0, 40000, 460,0.000000 }, - {1518,1519, 0, 0, 233, 233,0.000000 }, - {1520,1521, 0, 0, 40000, 213,0.000000 }, - {1522,1523, 0, 0, 1233, 1233,0.000000 }, - {1524,1525, 0, 0, 40000, 626,0.000000 }, - {1526,1527, 0, 0, 40000, 446,0.000000 }, - {1528,1529, 0, 0, 40000, 320,0.000000 }, - { 111,1530, 0, 0, 786, 786,0.000000 }, - {1531,1532, 0, 0, 20, 20,0.000000 }, - { 115,1533, 0, 0, 26, 26,0.000000 }, - {1534,1535, 0, 0, 166, 166,0.000000 }, - {1536,1537, 0, 0, 2280, 2280,0.000000 }, - {1538,1539, 0, 0, 280, 280,0.000000 }, - {1540, 339, 0, 0, 580, 580,0.000000 }, - {1541, 339, 0, 0, 4613, 4613,0.000000 }, - {1542,1543, 0, 0, 440, 440,0.000000 }, - {1544,1545, 0, 0, 153, 153,0.000000 }, - {1546,1547, 0, 0, 40000, 53,0.000000 }, - { 364, 365, 44, 0, 20, 20,0.000000 }, - { 129,1548, 48, 0, 66, 66,0.000000 }, - { 367, 368, 58, 0, 53, 53,0.000000 }, - { 129,1549, 60, 0, 73, 73,0.000000 }, - {1550,1551, 48, 0, 93, 93,0.000000 }, - { 132,1552, 43, 0, 13, 13,0.000000 }, - {1550,1551, 49, 0, 120, 120,0.000000 }, - {1553,1554, 43, 0, 26, 26,0.000000 }, - {1550,1551, 51, 0, 153, 153,0.000000 }, - { 134,1555, 43, 0, 146, 146,0.000000 }, - {1550,1551, 54, 0, 106, 106,0.000000 }, - {1550,1551, 57, 0, 100, 100,0.000000 }, - { 380, 381, 72, 0, 40000, 0,0.000000 }, - {1550,1551, 60, 0, 106, 106,0.000000 }, - {1556,1557, 70, 0, 246, 246,0.000000 }, - { 374, 375, 60, 0, 40000, 0,0.000000 }, - {1558,1559, 36, 0, 360, 360,0.000000 }, - {1560,1561, 65, 0, 113, 113,0.000000 }, - {1562,1563, 84, 0, 40000, 0,0.000000 }, - {1564,1565, 59, 0, 133, 133,0.000000 }, - {1566,1567, 84, 0, 40000, 0,0.000000 }, - {1568,1569, 35, 0, 53, 53,0.000000 }, - {1570,1571, 44, 0, 273, 273,0.000000 }, - {1572,1573, 67, 0, 66, 66,0.000000 }, - {1574,1575, 66, 0, 46, 46,0.000000 }, - { 145,1576, 59, 0, 13, 13,0.000000 }, - {1577,1578, 51, 0, 40, 40,0.000000 }, - {1579,1580, 45, 0, 40, 40,0.000000 }, - {1581,1582, 71, 0, 120, 120,0.000000 }, - { 149,1583, 60, 0, 180, 180,0.000000 }, - {1584,1585, 58, 0, 166, 166,0.000000 }, - {1586,1587, 53, 0, 140, 140,0.000000 }, - { 397,1588, 64, 0, 86, 86,0.000000 }, - {1589,1590, 71, 0, 13, 13,0.000000 }, - {1591,1592, 61, 0, 313, 313,0.000000 }, - {1593,1594, 61, 0, 513, 513,0.000000 }, - { 391, 392, 48, 0, 80, 80,0.000000 }, - { 391, 393, 48, 0, 80, 80,0.000000 }, - {1595,1596, 69, 0, 20, 20,0.000000 }, - { 159,1597, 68, 0, 20, 20,0.000000 }, - { 159,1597, 63, 0, 33, 33,0.000000 }, - {1598,1599, 74, 0, 333, 333,0.000000 }, - {1600,1601, 60, 0, 380, 380,0.000000 }, - {1602,1603, 80, 0, 60, 60,0.000000 }, - {1604,1605, 64, 0, 646, 646,0.000000 }, - {1606,1607, 69, 0, 33, 33,0.000000 }, - { 398, 399, 55, 0, 500, 500,0.000000 }, - {1608,1609, 75, 0, 346, 346,0.000000 }, - {1610,1611, 68, 0, 20, 20,0.000000 }, - {1612,1613, 48, 0, 46, 46,0.000000 }, - {1614,1615, 53, 0, 40, 40,0.000000 }, - {1616,1616, 0, 0, 40000, 873,0.000000 }, - {1617,1617, 0, 0, 40000, 446,0.000000 }, - {1618,1618, 0, 0, 1020, 1020,0.000000 }, - {1619,1619, 0, 0, 40000, 300,0.000000 }, - {1620,1620, 0, 0, 40000, 780,0.000000 }, - {1621,1621, 0, 0, 1400, 1400,0.000000 }, - {1622,1622, 0, 0, 40000, 480,0.000000 }, - {1623,1623, 0, 0, 40000, 566,0.000000 }, - {1624,1624, 0, 0, 3220, 3220,0.000000 }, - {1625,1625, 0, 0, 40000, 6,0.000000 }, - {1626,1626, 0, 0, 40000, 20,0.000000 }, - {1627,1627, 0, 0, 40000, 20,0.000000 }, - {1628,1628, 0, 0, 40000, 1180,0.000000 }, - {1629,1629, 0, 0, 40000, 20,0.000000 }, - {1630,1630, 0, 0, 40000, 6,0.000000 }, - {1631,1631, 0, 0, 40000, 6,0.000000 }, - {1632,1632, 0, 0, 40000, 280,0.000000 }, - {1633,1633, 0, 0, 40000, 6,0.000000 }, - {1634,1634, 0, 0, 40000, 6,0.000000 }, - {1635,1635, 0, 0, 40000, 6,0.000000 }, - {1636,1636, 0, 0, 340, 26,0.000000 }, - {1637,1637, 0, 0, 1000, 1000,0.000000 }, - {1638,1638, 0, 0, 40000, 200,0.000000 }, - {1639,1639, 0, 0, 460, 460,0.000000 }, - {1640,1640, 0, 0, 40000, 146,0.000000 }, - {1641,1641, 0, 0, 40000, 146,0.000000 }, - {1642,1642, 0, 0, 40000, 233,0.000000 }, - {1643,1643, 0, 0, 40000, 480,0.000000 }, - {1644,1644, 0, 0, 40000, 6,0.000000 }, - {1645,1645, 0, 0, 40000, 6,0.000000 }, - {1646,1646, 0, 0, 40000, 6,0.000000 }, - {1647,1647, 0, 0, 40000, 6,0.000000 }, - {1648,1648, 0, 0, 40000, 6,0.000000 }, - {1649,1649, 0, 0, 40000, 6,0.000000 }, - {1650,1650, 0, 0, 40000, 53,0.000000 }, - {1651,1651, 0, 0, 40000, 480,0.000000 }, - {1652,1652, 0, 0, 40000, 286,0.000000 }, - {1653,1653, 0, 0, 40000, 106,0.000000 }, - {1654,1654, 0, 0, 40000, 413,0.000000 }, - {1655,1655, 0, 0, 1213, 1213,0.000000 }, - {1656,1656, 0, 0, 513, 513,0.000000 }, - {1657,1657, 0, 0, 40000, 160,0.000000 }, - {1658,1658, 0, 0, 40000, 153,0.000000 }, - {1659,1659, 0, 0, 40000, 1973,0.000000 }, - {1660,1660, 0, 0, 40000, 3593,0.000000 }, - {1661,1661, 0, 0, 40000, 1120,0.000000 }, - {1662,1662, 0, 0, 620, 620,0.000000 }, - {1663,1663, 0, 0, 1740, 1740,0.000000 }, - {1664,1664, 0, 0, 940, 940,0.000000 }, - {1665,1665, 0, 0, 40000, 260,0.000000 }, - {1666,1666, 0, 0, 1900, 1900,0.000000 }, - {1667,1667, 0, 0, 40000, 426,0.000000 }, - {1668,1668, 12, 0, 66, 66,0.000000 }, - {1669,1669, 48, 0, 100, 100,0.000000 }, - { 736, 736, 52, 0, 80, 80,0.000000 }, - {1670,1670, 48, 0, 153, 153,0.000000 }, - {1670,1670, 36, 0, 146, 146,0.000000 }, - { 377, 377, 84, 0, 73, 73,0.000000 }, - { 730, 730, 95, 0, 600, 600,0.000000 }, - {1669,1669, 84, 0, 86, 86,0.000000 }, - { 755, 755, 20, 0, 200, 200,0.000000 }, - { 755, 755, 22, 0, 193, 193,0.000000 }, - { 755, 755, 24, 0, 200, 200,0.000000 }, - {1671,1671, 0, 0, 400, 400,0.000000 }, - {1672,1672, 0, 0, 460, 460,0.000000 }, - {1673,1673, 0, 0, 566, 566,0.000000 }, - {1674,1674, 0, 0, 40, 40,0.000000 }, - {1675,1675, 0, 0, 913, 913,0.000000 }, - {1676,1676, 0, 0, 940, 940,0.000000 }, - {1677,1677, 0, 0, 553, 553,0.000000 }, - {1678,1678, 0, 0, 653, 653,0.000000 }, - {1679,1679, 0, 0, 140, 140,0.000000 }, - {1680,1680, 0, 0, 440, 440,0.000000 }, - {1681,1681, 0, 0, 493, 493,0.000000 }, - {1682,1682, 0, 0, 40000, 213,0.000000 }, - {1683,1683, 0, 0, 246, 246,0.000000 }, - {1684,1684, 0, 0, 140, 140,0.000000 }, - {1685,1685, 0, 0, 880, 880,0.000000 }, - {1686,1686, 0, 0, 700, 700,0.000000 }, - {1687,1687, 0, 0, 40000, 0,0.000000 }, - {1688,1688, 0, 0, 40000, 6,0.000000 }, - {1689,1689, 0, 0, 86, 86,0.000000 }, - {1690,1690, 0, 0, 40000, 6,0.000000 }, - {1691,1691, 0, 0, 40000, 6,0.000000 }, - {1692,1692, 0, 0, 40000, 6,0.000000 }, - {1693,1693, 0, 0, 40000, 6,0.000000 }, - {1694,1694, 0, 0, 440, 440,0.000000 }, - {1695,1695, 0, 0, 440, 440,0.000000 }, - {1696,1696, 0, 0, 100, 0,0.000000 }, - {1697,1697, 0, 0, 1846, 1846,0.000000 }, - {1698,1698, 0, 0, 40, 40,0.000000 }, - {1699,1699, 0, 0, 6580, 6580,0.000000 }, - {1700,1700, 0, 0, 1846, 1846,0.000000 }, - {1701,1701, 0, 0, 1080, 1080,0.000000 }, - {1702,1702, 0, 0, 40000, 0,0.000000 }, - {1703,1703, 0, 0, 1020, 1020,0.000000 }, - {1704,1704, 0, 0, 40000, 53,0.000000 }, - {1705,1705, 0, 0, 40000, 0,0.000000 }, - {1706,1706, 0, 0, 40000, 0,0.000000 }, - {1707,1707, 0, 0, 40000, 53,0.000000 }, - {1708,1708, 0, 0, 40000, 0,0.000000 }, - {1709,1709, 0, 0, 40000, 26,0.000000 }, - {1710,1710, 0, 0, 626, 626,0.000000 }, - {1711,1711, 0, 0, 40000, 26,0.000000 }, - {1712,1712, 0, 0, 1226, 13,0.000000 }, - {1713,1713, 0, 0, 40000, 0,0.000000 }, - {1714,1714, 0, 0, 3980, 13,0.000000 }, - {1715,1715, 0, 0, 253, 253,0.000000 }, - {1716,1716, 0, 0, 940, 940,0.000000 }, - {1717,1717, 0, 0, 126, 126,0.000000 }, - {1718,1718, 0, 0, 3766, 13,0.000000 }, - {1719,1719, 0, 0, 660, 200,0.000000 }, - {1720,1720, 0, 0, 40000, 20,0.000000 }, - {1721,1721, 0, 0, 40000, 20,0.000000 }, - {1722,1722, 0, 0, 40000, 146,0.000000 }, - {1723,1723, 0, 0, 40000, 26,0.000000 }, - {1724,1724, 0, 0, 40000, 140,0.000000 }, - {1725,1725, 0, 0, 260, 260,0.000000 }, - {1726,1726, 0, 0, 40000, 0,0.000000 }, - {1727,1727, 0, 0, 126, 0,0.000000 }, - {1728,1728, 0, 0, 386, 6,0.000000 }, - {1729,1729, 0, 0, 40000, 33,0.000000 }, - {1730,1730, 0, 0, 126, 33,0.000000 }, - {1731,1731, 0, 0, 1580, 1580,0.000000 }, - {1732,1732, 0, 0, 40000, 6,0.000000 }, - {1733,1733, 0, 0, 40000, 6,0.000000 }, - {1734,1734, 0, 0, 40000, 6,0.000000 }, - {1735,1735, 0, 0, 40000, 13,0.000000 }, - {1736,1736, 0, 0, 40000, 13,0.000000 }, - {1737,1737, 0, 0, 40000, 20,0.000000 }, - {1738,1738, 0, 0, 40000, 13,0.000000 }, - {1739,1739, 0, 0, 40000, 13,0.000000 }, - {1740,1740, 0, 0, 40000, 73,0.000000 }, - {1741,1741, 0, 0, 40000, 6,0.000000 }, - {1742,1742, 0, 0, 40000, 6,0.000000 }, - {1743,1743, 0, 0, 40000, 20,0.000000 }, - {1744,1744, 0, 0, 993, 993,0.000000 }, - {1745,1745, 0, 0, 40000, 20,0.000000 }, - {1746,1746, 0, 0, 40000, 0,0.000000 }, - {1747,1747, 0, 0, 40000, 0,0.000000 }, - {1748,1748, 0, 0, 933, 6,0.000000 }, - {1749,1749, 0, 0, 40000, 20,0.000000 }, - {1750,1750, 0, 0, 40000, 6,0.000000 }, - {1751,1751, 0, 0, 40000, 13,0.000000 }, - {1752,1752, 0, 0, 40000, 26,0.000000 }, - {1753,1753, 0, 0, 40000, 0,0.000000 }, - {1754,1754, 0, 0, 1793, 1793,0.000000 }, - {1755,1755, 0, 0, 40000, 106,0.000000 }, - {1756,1756, 0, 0, 40000, 46,0.000000 }, - {1757,1757, 0, 0, 40000, 33,0.000000 }, - {1758,1758, 0, 0, 40000, 286,0.000000 }, - {1759,1759, 0, 0, 40000, 906,0.000000 }, - {1760,1760, 0, 0, 40000, 220,0.000000 }, - {1761,1761, 0, 0, 40000, 53,0.000000 }, - {1762,1762, 0, 0, 40000, 40,0.000000 }, - {1763,1763, 0, 0, 3446, 3446,0.000000 }, - {1764,1764, 0, 0, 860, 13,0.000000 }, - {1765,1765, 0, 0, 513, 513,0.000000 }, - {1766,1766, 0, 0, 1846, 1846,0.000000 }, - {1767,1767, 0, 0, 973, 973,0.000000 }, - {1768,1768, 0, 0, 40000, 366,0.000000 }, - {1769,1769, 0, 0, 1426, 1426,0.000000 }, - {1770,1770, 0, 0, 40000, 686,0.000000 }, - {1771,1771, 0, 0, 1060, 1060,0.000000 }, - {1772,1772, 0, 0, 13, 13,0.000000 }, - {1773,1773, 0, 0, 380, 380,0.000000 }, - {1774,1774, 0, 0, 146, 146,0.000000 }, - {1775,1775, 0, 0, 166, 166,0.000000 }, - {1776,1776, 0, 0, 40000, 6,0.000000 }, - {1777,1777, 0, 0, 40000, 0,0.000000 }, - {1778,1778, 0, 0, 40000, 66,0.000000 }, - {1779,1779, 0, 0, 1473, 1473,0.000000 }, - {1780,1780, 0, 0, 113, 113,0.000000 }, - {1781,1781, 0, 0, 353, 353,0.000000 }, - {1782,1782, 0, 0, 46, 46,0.000000 }, - {1783,1783, 0, 0, 86, 86,0.000000 }, - {1784,1784, 0, 0, 60, 60,0.000000 }, - {1785,1785, 0, 0, 2280, 2280,0.000000 }, - {1786,1786, 0, 0, 366, 366,0.000000 }, - {1787,1787, 0, 0, 1713, 1713,0.000000 }, - {1788,1788, 0, 0, 206, 206,0.000000 }, - {1789,1789, 0, 0, 40000, 6,0.000000 }, - {1790,1790, 0, 0, 40000, 0,0.000000 }, - {1791,1791, 0, 0, 40000, 553,0.000000 }, - {1792,1792, 0, 0, 160, 160,0.000000 }, - {1793,1793, 48, 0, 46, 46,0.000000 }, - {1794,1794, 48, 0, 13, 13,0.000000 }, - {1795,1795, 60, 0, 46, 46,0.000000 }, - {1796,1796, 60, 0, 33, 33,0.000000 }, - {1797,1797, 70, 0, 33, 33,0.000000 }, - {1798,1798, 51, 0, 160, 160,0.000000 }, - {1799,1799, 60, 0, 40, 40,0.000000 }, - {1798,1798, 54, 0, 140, 140,0.000000 }, - {1800,1800, 60, 0, 53, 53,0.000000 }, - {1798,1798, 56, 0, 140, 140,0.000000 }, - {1801,1801, 60, 0, 300, 300,0.000000 }, - {1798,1798, 61, 0, 166, 166,0.000000 }, - {1798,1798, 63, 0, 166, 166,0.000000 }, - {1802,1802, 48, 0, 300, 300,0.000000 }, - {1798,1798, 68, 0, 133, 133,0.000000 }, - {1803,1803, 60, 0, 393, 393,0.000000 }, - {1804,1804, 60, 0, 313, 313,0.000000 }, - {1805,1805, 66, 0, 100, 100,0.000000 }, - {1806,1806, 60, 0, 306, 306,0.000000 }, - { 379, 379, 59, 0, 40, 40,0.000000 }, - {1802,1802, 64, 0, 306, 306,0.000000 }, - {1807,1807, 48, 0, 566, 566,0.000000 }, - {1808,1808, 56, 0, 26, 26,0.000000 }, - {1809,1809, 53, 0, 73, 73,0.000000 }, - {1810,1810, 65, 0, 13, 13,0.000000 }, - {1811,1811, 49, 0, 86, 86,0.000000 }, - {1811,1811, 43, 0, 86, 86,0.000000 }, - { 386, 386, 65, 0, 86, 86,0.000000 }, - { 386, 386, 60, 0, 86, 86,0.000000 }, - {1812,1812, 70, 0, 80, 80,0.000000 }, - {1812,1812, 65, 0, 100, 100,0.000000 }, - {1813,1813, 60, 0, 40, 40,0.000000 }, - {1814,1814, 60, 0, 33, 33,0.000000 }, - {1815,1815, 56, 0, 93, 93,0.000000 }, - {1816,1816, 53, 0, 280, 280,0.000000 }, - {1817,1817, 60, 0, 60, 60,0.000000 }, - {1818,1818, 48, 0, 180, 180,0.000000 }, - {1819,1819, 69, 0, 20, 20,0.000000 }, - { 328, 328, 67, 0, 20, 20,0.000000 }, - { 328, 328, 62, 0, 20, 20,0.000000 }, - {1820,1820, 65, 0, 220, 220,0.000000 }, - {1821,1821, 60, 0, 220, 220,0.000000 }, - {1822,1822, 63, 0, 26, 26,0.000000 }, - {1823,1823, 63, 0, 606, 606,0.000000 }, - {1824,1824, 67, 0, 86, 86,0.000000 }, - {1825,1825, 60, 0, 300, 300,0.000000 }, - {1825,1825, 72, 0, 273, 273,0.000000 }, - { 401, 401, 62, 0, 6, 6,0.000000 }, - {1826,1826, 48, 0, 13, 13,0.000000 }, - {1827,1827, 53, 0, 213, 213,0.000000 }, - {1828,1828, 60, 0, 93, 93,0.000000 }, - {1829,1829, 60, 0, 40, 40,0.000000 }, - {1830,1830, 60, 0, 20, 20,0.000000 }, - {1831,1831, 60, 0, 46, 46,0.000000 }, - {1832,1832, 0, 0, 126, 0,0.000000 }, - {1833,1833, 0, 0, 1240, 1240,0.000000 }, - {1834,1834, 0, 0, 433, 433,0.000000 }, - {1835,1835, 0, 0, 40000, 0,0.000000 }, - {1836,1836, 0, 0, 40000, 153,0.000000 }, - {1837,1837, 0, 0, 146, 106,0.000000 }, - {1838,1838, 0, 0, 126, 126,0.000000 }, - {1839,1839, 0, 0, 1740, 1740,0.000000 }, - {1840,1840, 0, 0, 440, 13,0.000000 }, - {1841,1841, 0, 0, 546, 546,0.000000 }, - {1842,1842, 0, 0, 1420, 1420,0.000000 }, - { 525, 525, 0, 0, 1220, 1220,0.000000 }, - {1843,1843, 0, 0, 40000, 140,0.000000 }, - {1844,1844, 0, 0, 3873, 3873,0.000000 }, - {1845,1845, 0, 0, 546, 546,0.000000 }, - {1846,1846, 0, 0, 333, 333,0.000000 }, - {1847,1847, 0, 0, 4933, 4933,0.000000 }, - {1848,1848, 0, 0, 126, 0,0.000000 }, - {1849,1849, 0, 0, 380, 380,0.000000 }, - {1850,1850, 0, 0, 40000, 6,0.000000 }, - {1851,1851, 0, 0, 273, 273,0.000000 }, - {1852,1852, 0, 0, 233, 233,0.000000 }, - {1853,1853, 0, 0, 40000, 233,0.000000 }, - {1854,1854, 0, 0, 1466, 6,0.000000 }, - {1855,1855, 0, 0, 1380, 1380,0.000000 }, - {1856,1856, 0, 0, 40000, 106,0.000000 }, - {1857,1857, 0, 0, 40000, 133,0.000000 }, - {1858,1858, 0, 0, 913, 913,0.000000 }, - {1859,1859, 0, 0, 60, 60,0.000000 }, - {1860,1860, 0, 0, 40000, 6,0.000000 }, - {1861,1861, 0, 0, 866, 866,0.000000 }, - {1862,1862, 0, 0, 4726, 4726,0.000000 }, - {1863,1863, 0, 0, 40, 40,0.000000 }, - {1864,1864, 0, 0, 1793, 1793,0.000000 }, - {1865,1865, 0, 0, 246, 246,0.000000 }, - {1866,1866, 0, 0, 40000, 133,0.000000 }, - {1867,1867, 0, 0, 2006, 2006,0.000000 }, - {1868,1868, 0, 0, 140, 140,0.000000 }, - {1869,1869, 0, 0, 40000, 106,0.000000 }, - {1870,1870, 0, 0, 460, 460,0.000000 }, - {1871,1871, 0, 0, 146, 146,0.000000 }, - {1872,1872, 0, 0, 273, 273,0.000000 }, - {1873,1873, 0, 0, 40000, 46,0.000000 }, - {1874,1874, 41, 0, 120, 120,0.000000 }, - {1875,1875, 70, 0, 13, 13,0.000000 }, - {1876,1876, 60, 0, 40, 40,0.000000 }, - {1877,1877, 80, 0, 13, 13,0.000000 }, - {1878,1878, 84, 0, 20, 20,0.000000 }, - {1879,1879, 72, 0, 133, 133,0.000000 }, - {1880,1880, 84, 0, 266, 266,0.000000 }, - { 128, 128, 70, 0, 13, 13,0.000000 }, - { 132, 132, 60, 0, 13, 13,0.000000 }, - {1881,1882, 0, 0, 40000, 173,0.000000 }, - {1883,1883, 0, 0, 260, 260,0.000000 }, - {1884,1885, 0, 0, 40000, 6,0.000000 }, - {1886,1887, 0, 0, 40000, 20,0.000000 }, - {1888,1889, 0, 0, 40000, 6,0.000000 }, - {1890,1890, 0, 0, 1020, 53,0.000000 }, - {1891,1891, 0, 0, 40000, 100,0.000000 }, - {1892,1892, 0, 0, 786, 340,0.000000 }, - {1893,1893, 0, 0, 40000, 140,0.000000 }, - {1894,1894, 0, 0, 86, 86,0.000000 }, - {1895,1895, 0, 0, 80, 40,0.000000 }, - {1896,1896, 0, 0, 40000, 86,0.000000 }, - {1897,1897, 0, 0, 173, 173,0.000000 }, - {1898,1898, 0, 0, 886, 886,0.000000 }, - {1899,1899, 0, 0, 466, 466,0.000000 }, - {1900,1900, 0, 0, 40000, 106,0.000000 }, - {1901,1901, 0, 0, 40000, 66,0.000000 }, - {1902,1902, 0, 0, 40000, 13,0.000000 }, - {1903,1903, 0, 0, 60, 60,0.000000 }, - {1904,1904, 0, 0, 1226, 1226,0.000000 }, - {1905,1905, 0, 0, 280, 280,0.000000 }, - {1906,1906, 0, 0, 40000, 153,0.000000 }, - {1907,1907, 0, 0, 40000, 173,0.000000 }, - {1908,1908, 0, 0, 40000, 340,0.000000 }, - {1909,1909, 0, 0, 166, 166,0.000000 }, - { 501, 501, 0, 0, 86, 86,0.000000 }, - {1910,1910, 0, 0, 40000, 20,0.000000 }, - {1911,1911, 0, 0, 20, 20,0.000000 }, - {1912,1912, 0, 0, 600, 600,0.000000 }, - {1913,1913, 0, 0, 40000, 2393,0.000000 }, - {1914,1914, 0, 0, 166, 166,0.000000 }, - { 511, 511, 0, 0, 586, 586,0.000000 }, - {1915,1915, 0, 0, 73, 73,0.000000 }, - {1910,1910, 60, 0, 40000, 26,0.000000 }, - { 511, 511, 72, 0, 493, 493,0.000000 }, - {1915,1915, 84, 0, 60, 60,0.000000 }, - {1916,1916, 0, 0, 2080, 2080,0.000000 }, - {1917,1917, 0, 0, 593, 593,0.000000 }, - {1918,1918, 0, 0, 600, 600,0.000000 }, - {1919,1919, 0, 0, 940, 940,0.000000 }, - {1920,1920, 0, 0, 940, 940,0.000000 }, - {1921,1921, 0, 0, 940, 940,0.000000 }, - {1922,1922, 0, 0, 853, 853,0.000000 }, - {1923,1923, 0, 0, 893, 893,0.000000 }, - {1924,1924, 0, 0, 40000, 73,0.000000 }, - {1925,1925, 0, 0, 40000, 33,0.000000 }, - {1926,1926, 0, 0, 40000, 20,0.000000 }, - {1927,1927, 0, 0, 40000, 0,0.000000 }, - {1928,1928, 0, 0, 40000, 193,0.000000 }, - {1929,1929, 0, 0, 40000, 133,0.000000 }, - {1930,1930, 0, 0, 40000, 153,0.000000 }, - {1931,1931, 0, 0, 1146, 1146,0.000000 }, - {1932,1932, 0, 0, 960, 960,0.000000 }, - {1933,1933, 0, 0, 2406, 2406,0.000000 }, - {1934,1934, 0, 0, 2406, 2406,0.000000 }, - {1935,1935, 0, 0, 40000, 0,0.000000 }, - {1936,1936, 0, 0, 40000, 6,0.000000 }, - {1937,1937, 0, 0, 40000, 0,0.000000 }, - {1938,1938, 0, 0, 40000, 0,0.000000 }, - {1939,1939, 0, 0, 40000, 26,0.000000 }, - {1940,1940, 0, 0, 1426, 1426,0.000000 }, - {1941,1941, 0, 0, 40000, 766,0.000000 }, - {1942,1942, 0, 0, 40000, 453,0.000000 }, - {1943,1943, 0, 0, 40000, 486,0.000000 }, - {1944,1944, 0, 0, 40000, 106,0.000000 }, - {1945,1945, 0, 0, 2273, 2273,0.000000 }, - {1946,1946, 0, 0, 40000, 33,0.000000 }, - {1947,1947, 0, 0, 1226, 1226,0.000000 }, - {1948,1948, 0, 0, 40000, 6,0.000000 }, - {1949,1949, 0, 0, 40000, 1966,0.000000 }, - {1950,1950, 0, 0, 1153, 1153,0.000000 }, - {1951,1951, 0, 0, 40000, 6,0.000000 }, - {1952,1952, 0, 0, 1473, 1473,0.000000 }, - {1953,1953, 0, 0, 40000, 20,0.000000 }, - {1954,1954, 0, 0, 466, 33,0.000000 }, - {1955,1955, 0, 0, 833, 833,0.000000 }, - {1956,1956, 0, 0, 40000, 0,0.000000 }, - {1957,1957, 0, 0, 40000, 33,0.000000 }, - {1958,1958, 0, 0, 40000, 126,0.000000 }, - {1959,1959, 0, 0, 40000, 33,0.000000 }, - {1960,1960, 0, 0, 280, 280,0.000000 }, - {1961,1961, 0, 0, 40000, 266,0.000000 }, - {1962,1962, 0, 0, 40000, 46,0.000000 }, - {1963,1963, 0, 0, 40000, 266,0.000000 }, - {1964,1964, 0, 0, 40000, 0,0.000000 }, - {1965,1965, 0, 0, 40000, 113,0.000000 }, - {1966,1966, 0, 0, 800, 800,0.000000 }, - {1967,1967, 0, 0, 1206, 1206,0.000000 }, - {1968,1968, 0, 0, 1080, 1080,0.000000 }, - {1969,1969, 0, 0, 40000, 13,0.000000 }, - {1970,1970, 0, 0, 546, 546,0.000000 }, - {1971,1971, 0, 0, 40000, 6,0.000000 }, - {1972,1972, 0, 0, 40000, 20,0.000000 }, - {1973,1973, 0, 0, 1233, 20,0.000000 }, - {1974,1974, 0, 0, 40000, 0,0.000000 }, - {1975,1975, 0, 0, 40000, 0,0.000000 }, - {1976,1976, 0, 0, 466, 6,0.000000 }, - {1977,1977, 0, 0, 206, 206,0.000000 }, - {1978,1978, 0, 0, 40000, 6,0.000000 }, - {1979,1979, 0, 0, 40000, 6,0.000000 }, - {1980,1980, 0, 0, 40000, 6,0.000000 }, - {1981,1981, 0, 0, 40000, 6,0.000000 }, - {1982,1982, 0, 0, 40000, 0,0.000000 }, - {1983,1983, 0, 0, 40000, 0,0.000000 }, - {1984,1984, 0, 0, 40000, 0,0.000000 }, - {1985,1985, 0, 0, 40000, 180,0.000000 }, - {1986,1986, 0, 0, 40000, 53,0.000000 }, - {1987,1987, 0, 0, 40000, 53,0.000000 }, - {1988,1988, 0, 0, 40000, 6,0.000000 }, - {1989,1989, 0, 0, 40000, 6,0.000000 }, - {1990,1990, 0, 0, 100, 100,0.000000 }, - {1991,1991, 0, 0, 40000, 73,0.000000 }, - {1992,1992, 0, 0, 60, 60,0.000000 }, - {1993,1993, 0, 0, 40000, 0,0.000000 }, - {1994,1994, 0, 0, 40000, 0,0.000000 }, - {1995,1995, 0, 0, 40000, 0,0.000000 }, - {1996,1996, 0, 0, 40000, 6,0.000000 }, - {1997,1997, 0, 0, 40000, 0,0.000000 }, - {1998,1998, 0, 0, 40000, 0,0.000000 }, - {1999,1999, 0, 0, 40000, 0,0.000000 }, - {2000,2000, 0, 0, 40000, 233,0.000000 }, - {2001,2001, 0, 0, 40000, 233,0.000000 }, - {2002,2002, 0, 0, 620, 620,0.000000 }, - {2003,2003, 0, 0, 1740, 1740,0.000000 }, - {2004,2004, 0, 0, 1153, 1153,0.000000 }, - {2005,2005, 0, 0, 920, 920,0.000000 }, - {2006,2006, 0, 0, 153, 153,0.000000 }, - {2007,2007, 0, 0, 526, 526,0.000000 }, - {2008,2008, 0, 0, 40000, 6,0.000000 }, - {2009,2009, 0, 0, 40000, 40,0.000000 }, - {2010,2010, 0, 0, 40000, 53,0.000000 }, - {2011,2011, 0, 0, 40000, 160,0.000000 }, - {2012,2012, 0, 0, 40000, 6,0.000000 }, - {2013,2013, 0, 0, 1046, 1046,0.000000 }, - {2014,2014, 0, 0, 513, 513,0.000000 }, - {2015,2015, 0, 0, 40, 40,0.000000 }, - {2016,2016, 0, 0, 40, 40,0.000000 }, - {2017,2017, 0, 0, 93, 93,0.000000 }, - {2018,2018, 0, 0, 66, 66,0.000000 }, - {2019,2019, 0, 0, 13, 13,0.000000 }, - {2020,2020, 0, 0, 300, 300,0.000000 }, - {2021,2021, 0, 0, 40, 40,0.000000 }, - {2022,2022, 0, 0, 586, 586,0.000000 }, - {2023,2023, 0, 0, 260, 260,0.000000 }, - {2024,2024, 0, 0, 2406, 2406,0.000000 }, - {2025,2025, 0, 0, 126, 126,0.000000 }, - {2026,2026, 0, 0, 1220, 1220,0.000000 }, - {2027,2027, 0, 0, 386, 386,0.000000 }, - { 352, 352, 51, 0, 40000, 0,0.000000 }, - {2028,2028, 35, 0, 106, 106,0.000000 }, - {2028,2028, 36, 0, 93, 93,0.000000 }, - {2029,2029, 47, 0, 13, 13,0.000000 }, - {2030,2030, 38, 0, 106, 106,0.000000 }, - {2019,2019, 39, 0, 20, 20,0.000000 }, - {2031,2031, 45, 0, 80, 80,0.000000 }, - { 492, 492, 41, 0, 26, 26,0.000000 }, - {2032,2032, 42, 0, 33, 33,0.000000 }, - {2033,2033, 44, 0, 160, 160,0.000000 }, - { 492, 492, 48, 0, 40, 40,0.000000 }, - {2034,2034, 46, 0, 600, 600,0.000000 }, - { 492, 492, 53, 0, 26, 26,0.000000 }, - { 167, 167, 56, 0, 160, 160,0.000000 }, - {2035,2035, 61, 0, 93, 93,0.000000 }, - {2036,2036, 56, 0, 353, 353,0.000000 }, - {2037,2037, 60, 0, 40, 40,0.000000 }, - { 144, 144, 59, 0, 40, 40,0.000000 }, - {2038,2038, 59, 0, 13, 13,0.000000 }, - { 169, 169, 51, 0, 40, 40,0.000000 }, - { 169, 169, 45, 0, 40, 40,0.000000 }, - {2039,2039, 72, 0, 126, 126,0.000000 }, - {2040,2040, 60, 0, 153, 153,0.000000 }, - {2041,2041, 58, 0, 40, 40,0.000000 }, - {2042,2042, 53, 0, 40, 40,0.000000 }, - {2043,2043, 73, 0, 26, 26,0.000000 }, - { 158, 158, 75, 0, 20, 20,0.000000 }, - {2044,2044, 0, 0, 1226, 1226,0.000000 }, - {2045,2045, 0, 0, 493, 493,0.000000 }, - {2046,2046, 0, 0, 620, 620,0.000000 }, - {2047,2047, 0, 0, 280, 280,0.000000 }, - {2048,2048, 0, 0, 260, 260,0.000000 }, - {2049,2049, 0, 0, 40000, 1093,0.000000 }, - {2050,2050, 0, 0, 40000, 233,0.000000 }, - {2051,2051, 0, 0, 120, 120,0.000000 }, - {2052,2052, 0, 0, 40000, 926,0.000000 }, - {2053,2053, 0, 0, 40000, 926,0.000000 }, - {2054,2054, 0, 0, 40000, 233,0.000000 }, - {2055,2055, 0, 0, 40000, 280,0.000000 }, - {2056,2056, 0, 0, 40000, 6,0.000000 }, - {2057,2057, 0, 0, 40000, 153,0.000000 }, - {2058,2058, 0, 0, 286, 286,0.000000 }, - {2059,2059, 0, 0, 286, 286,0.000000 }, - {2060,2060, 0, 0, 40000, 0,0.000000 }, - {2061,2061, 0, 0, 680, 680,0.000000 }, - {2062,2062, 0, 0, 280, 280,0.000000 }, - {2063,2063, 0, 0, 40000, 200,0.000000 }, - {2064,2064, 0, 0, 40, 40,0.000000 }, - {2065,2065, 0, 0, 1580, 1580,0.000000 }, - {2066,2066, 0, 0, 140, 133,0.000000 }, - {2067,2067, 0, 0, 40000, 213,0.000000 }, - {2068,2068, 0, 0, 613, 613,0.000000 }, - {2069,2069, 0, 0, 293, 293,0.000000 }, - {2070,2070, 0, 0, 160, 160,0.000000 }, - {2071,2071, 0, 0, 146, 13,0.000000 }, - {2072,2072, 0, 0, 40000, 6,0.000000 }, - {2073,2073, 0, 0, 40000, 133,0.000000 }, - {2074,2074, 0, 0, 40000, 140,0.000000 }, - {2075,2075, 0, 0, 40000, 66,0.000000 }, - {2076,2076, 0, 0, 40000, 40,0.000000 }, - {2077,2077, 0, 0, 40000, 153,0.000000 }, - {2078,2078, 0, 0, 593, 593,0.000000 }, - {2079,2079, 0, 0, 40000, 40,0.000000 }, - {2080,2080, 0, 0, 4480, 4480,0.000000 }, - {2081,2081, 0, 0, 3600, 313,0.000000 }, - {2082,2082, 0, 0, 40000, 413,0.000000 }, - {2083,2083, 0, 0, 40000, 566,0.000000 }, - {2084,2084, 0, 0, 8420, 80,0.000000 }, - {2085,2085, 0, 0, 40000, 926,0.000000 }, - {2086,2086, 0, 0, 40000, 853,0.000000 }, - {2087,2087, 0, 0, 40000, 853,0.000000 }, - {2088,2088, 0, 0, 40000, 853,0.000000 }, - {2089,2089, 0, 0, 40000, 873,0.000000 }, - {2090,2090, 0, 0, 40000, 1780,0.000000 }, - {2091,2091, 0, 0, 40000, 1673,0.000000 }, - {2092,2092, 0, 0, 4026, 4026,0.000000 }, - {2093,2093, 0, 0, 1773, 153,0.000000 }, - {2094,2094, 0, 0, 1446, 1446,0.000000 }, - {2095,2095, 0, 0, 633, 633,0.000000 }, - {2096,2096, 0, 0, 333, 333,0.000000 }, - {2097,2097, 0, 0, 193, 193,0.000000 }, - {2098,2098, 0, 0, 86, 86,0.000000 }, - {2099,2099, 0, 0, 246, 246,0.000000 }, - {2100,2100, 0, 0, 40000, 6,0.000000 }, - {2101,2101, 0, 0, 40000, 6,0.000000 }, - {2102,2102, 0, 0, 313, 313,0.000000 }, - {2103,2103, 0, 0, 160, 160,0.000000 }, - {2104,2104, 0, 0, 46, 46,0.000000 }, - {2105,2105, 0, 0, 100, 100,0.000000 }, - {2106,2106, 0, 0, 2313, 2313,0.000000 }, - {2107,2107, 0, 0, 306, 306,0.000000 }, - {2108,2108, 0, 0, 40000, 2180,0.000000 }, - {2109,2109, 0, 0, 40000, 133,0.000000 }, - {2110,2110, 0, 0, 40000, 126,0.000000 }, - {2111,2111, 0, 0, 40000, 146,0.000000 }, - { 752, 752, 60, 0, 40, 40,0.000000 }, - { 755, 755, 12, 0, 160, 160,0.000000 }, - {2112,2112, 89, 0, 13, 13,0.000000 }, - {2113,2113, 89, 0, 206, 206,0.000000 }, - { 755, 755, 14, 0, 160, 160,0.000000 }, - { 755, 755, 16, 0, 160, 160,0.000000 }, - {2114,2114, 84, 0, 513, 513,0.000000 }, - { 755, 755, 19, 0, 160, 160,0.000000 }, - {2115,2115, 38, 0, 60, 60,0.000000 }, - {2116,2116, 36, 0, 20, 20,0.000000 }, - { 755, 755, 28, 0, 193, 193,0.000000 }, - { 755, 755, 26, 0, 200, 200,0.000000 }, - { 755, 755, 35, 0, 200, 200,0.000000 }, - { 755, 755, 30, 0, 193, 193,0.000000 }, - {2117,2117, 60, 0, 73, 73,0.000000 }, - {2104,2104, 60, 0, 40, 40,0.000000 }, - {2104,2104, 55, 0, 46, 46,0.000000 }, - { 730, 730, 94, 0, 626, 626,0.000000 }, - {2118,2118, 0, 0, 280, 280,0.000000 }, - {2119,2119, 0, 0, 1446, 1446,0.000000 }, - {2120,2120, 0, 0, 40000, 53,0.000000 }, - {2121,2121, 0, 0, 40000, 20,0.000000 }, - {2122,2122, 0, 0, 40000, 20,0.000000 }, - {2123,2123, 0, 0, 3106, 3106,0.000000 }, - {2124,2124, 0, 0, 40, 66,0.000000 }, - {2125,2125, 0, 0, 40000, 106,0.000000 }, - {2126,2126, 0, 0, 40000, 6,0.000000 }, - {2127,2127, 0, 0, 40000, 13,0.000000 }, - {2128,2128, 0, 0, 40000, 6,0.000000 }, - {2129,2129, 0, 0, 40000, 6,0.000000 }, - {2130,2130, 0, 0, 40000, 6,0.000000 }, - {2131,2131, 0, 0, 40000, 13,0.000000 }, - {2132,2132, 0, 0, 40000, 6,0.000000 }, - {2133,2133, 0, 0, 2060, 13,0.000000 }, - {2134,2134, 0, 0, 40000, 53,0.000000 }, - {2135,2135, 0, 0, 2886, 2886,0.000000 }, - {2136,2136, 0, 0, 40000, 126,0.000000 }, - {2137,2137, 0, 0, 5280, 100,0.000000 }, - {2138,2138, 0, 0, 140, 140,0.000000 }, - {2139,2139, 0, 0, 4553, 20,0.000000 }, - {2140,2140, 0, 0, 513, 513,0.000000 }, - {2141,2141, 60, 0, 40, 40,0.000000 }, - {2141,2141, 44, 0, 40, 40,0.000000 }, - {2142,2142, 47, 0, 40, 40,0.000000 }, - {2143,2143, 47, 0, 60, 60,0.000000 }, - {2144,2144, 62, 0, 606, 606,0.000000 }, - {2145,2145, 93, 0, 226, 226,0.000000 }, - {2146,2146, 50, 0, 80, 80,0.000000 }, - {2145,2145, 40, 0, 420, 420,0.000000 }, - {2147,2147, 60, 0, 20, 20,0.000000 }, - { 898, 898, 60, 0, 46, 46,0.000000 }, - {2147,2147, 57, 0, 20, 20,0.000000 }, - { 900, 900, 42, 0, 193, 193,0.000000 }, - { 900, 900, 38, 0, 193, 193,0.000000 }, - { 908, 908, 88, 0, 33, 33,0.000000 }, - {2148,2148, 0, 0, 1553, 1553,0.000000 }, - {2149,2149, 0, 0, 40000, 6,0.000000 }, - {2150,2150, 0, 0, 993, 993,0.000000 }, - {2151,2151, 0, 0, 40000, 26,0.000000 }, - {2152,2152, 0, 0, 29720, 80,0.000000 }, - {2153,2153, 0, 0, 40000, 306,0.000000 }, - {2154,2154, 0, 0, 700, 700,0.000000 }, - {2155,2155, 0, 0, 880, 880,0.000000 }, - {2156,2156, 0, 0, 40000, 6,0.000000 }, - {2157,2157, 0, 0, 1046, 1046,0.000000 }, - {2158,2158, 0, 0, 100, 100,0.000000 }, - {2159,2159, 0, 0, 40, 40,0.000000 }, - { 136, 136, 0, 0, 640, 640,0.000000 }, - { 168, 168, 0, 0, 40, 40,0.000000 }, - { 164, 164, 0, 0, 1220, 1220,0.000000 }, - { 167, 167, 0, 0, 160, 160,0.000000 }, - {2160,2160, 65, 0, 40, 40,0.000000 }, - {2161,2161, 21, 0, 200, 200,0.000000 }, - {2162, 173, 0, 0, 1513, 1513,0.000000 }, - {2163,2164, 0, 0, 653, 653,0.000000 }, - {2165,2166, 0, 0, 633, 633,0.000000 }, - {2167,2168, 0, 0, 913, 913,0.000000 }, - {2169,2170, 0, 0, 300, 300,0.000000 }, - {2171,2172, 0, 0, 1773, 1773,0.000000 }, - {2173,2174, 0, 0, 40000, 306,0.000000 }, - {2175,2174, 0, 0, 40000, 433,0.000000 }, - {2176, 299, 0, 0, 40000, 66,0.000000 }, - {2177,2178, 0, 0, 40000, 246,0.000000 }, - {2179,2180, 0, 0, 40000, 300,0.000000 }, - {2181,2182, 0, 0, 40000, 233,0.000000 }, - {2183,2184, 0, 0, 1740, 1740,0.000000 }, - { 127, 127, 65, 0, 66, 66,0.000000 }, - { 127, 127, 72, 0, 46, 46,0.000000 }, - { 364, 365, 52, 0, 20, 20,0.000000 }, - {2185,2186, 60, 0, 80, 80,0.000000 }, - {1550,1551, 47, 0, 100, 100,0.000000 }, - {1556,1557, 76, 0, 253, 253,0.000000 }, - { 374, 375, 84, 0, 40000, 0,0.000000 }, - {1564,1565, 83, 0, 73, 73,0.000000 }, - {1568,1569, 24, 0, 40, 40,0.000000 }, - {1556,1557, 77, 0, 253, 253,0.000000 }, - {1572,1573, 60, 0, 80, 80,0.000000 }, - {1574,1575, 65, 0, 46, 46,0.000000 }, - { 391, 392, 44, 0, 80, 80,0.000000 }, - { 391, 393, 40, 0, 40, 40,0.000000 }, - {1606,1607, 72, 0, 33, 33,0.000000 }, - { 398, 399, 73, 0, 400, 400,0.000000 }, - {1608,1609, 70, 0, 353, 353,0.000000 }, - {2187,2187, 0, 0, 40000, 140,0.000000 }, - {2188,2188, 0, 0, 40000, 153,0.000000 }, - {2189,2189, 0, 0, 453, 453,0.000000 }, - {2190,2190, 0, 0, 1300, 1300,0.000000 }, - {2191,2191, 0, 0, 46, 46,0.000000 }, - {2192,2192, 0, 0, 40000, 186,0.000000 }, - {2193,2193, 0, 0, 80, 80,0.000000 }, - {2194,2194, 0, 0, 40000, 6,0.000000 }, - {2195,2195, 0, 0, 186, 186,0.000000 }, - {2196,2196, 0, 0, 40000, 0,0.000000 }, - {2197,2197, 0, 0, 40000, 0,0.000000 }, - {2198,2198, 0, 0, 166, 0,0.000000 }, - {2199,2199, 0, 0, 40, 40,0.000000 }, - {2200,2200, 0, 0, 1740, 1740,0.000000 }, - { 528, 528, 0, 0, 140, 140,0.000000 }, - {2201,2201, 0, 0, 40000, 53,0.000000 }, - {2202,2202, 0, 0, 40, 40,0.000000 }, - {2203,2203, 0, 0, 80, 80,0.000000 }, - {2204,2204, 41, 0, 46, 46,0.000000 }, - {2205,2205, 84, 0, 40, 40,0.000000 }, - {2206,2206, 72, 0, 133, 133,0.000000 }, - { 741, 741, 48, 0, 133, 133,0.000000 }, - {2207,2207, 0, 0, 40, 40,0.000000 }, - {2208,2208, 0, 0, 940, 940,0.000000 }, - {2209,2209, 0, 0, 40000, 213,0.000000 }, - {2210,2210, 0, 0, 866, 866,0.000000 }, - {2211,2211, 0, 0, 40000, 0,0.000000 }, - {2212,2212, 0, 0, 40000, 6,0.000000 }, - {2213,2213, 0, 0, 1080, 1080,0.000000 }, - {2214,2214, 0, 0, 40000, 0,0.000000 }, - {2215,2215, 0, 0, 40000, 73,0.000000 }, - {2216,2216, 0, 0, 40000, 26,0.000000 }, - {2217,2217, 0, 0, 2360, 13,0.000000 }, - {2218,2218, 0, 0, 40000, 0,0.000000 }, - {2219,2219, 0, 0, 3126, 13,0.000000 }, - {2220,2220, 0, 0, 40000, 140,0.000000 }, - {2221,2221, 0, 0, 40000, 26,0.000000 }, - {2222,2222, 0, 0, 40000, 140,0.000000 }, - {2223,2223, 0, 0, 40000, 0,0.000000 }, - {2224,2224, 0, 0, 126, 0,0.000000 }, - {2225,2225, 0, 0, 40000, 6,0.000000 }, - {2226,2226, 0, 0, 40000, 33,0.000000 }, - {2227,2227, 0, 0, 40000, 6,0.000000 }, - {2228,2228, 0, 0, 40000, 6,0.000000 }, - {2229,2229, 0, 0, 40000, 0,0.000000 }, - {2230,2230, 0, 0, 40000, 6,0.000000 }, - {2231,2231, 0, 0, 40000, 20,0.000000 }, - {2232,2232, 0, 0, 40000, 6,0.000000 }, - {2233,2233, 0, 0, 40000, 26,0.000000 }, - {2234,2234, 0, 0, 40000, 266,0.000000 }, - {2235,2235, 0, 0, 40000, 40,0.000000 }, - {2236,2236, 0, 0, 3500, 3500,0.000000 }, - {2237,2237, 0, 0, 860, 20,0.000000 }, - {2238,2238, 0, 0, 513, 513,0.000000 }, - {2239,2239, 0, 0, 973, 973,0.000000 }, - {2240,2240, 0, 0, 1446, 1446,0.000000 }, - {2241,2241, 0, 0, 2280, 2280,0.000000 }, - {2242,2242, 0, 0, 1713, 1713,0.000000 }, - {2243,2243, 0, 0, 200, 200,0.000000 }, - {2244,2244, 0, 0, 40000, 6,0.000000 }, - {2245,2245, 0, 0, 40000, 0,0.000000 }, - {2246,2246, 0, 0, 140, 140,0.000000 }, - {2247,2247, 60, 0, 46, 46,0.000000 }, - {2248,2248, 60, 0, 306, 306,0.000000 }, - {2249,2249, 48, 0, 300, 300,0.000000 }, - {2250,2250, 60, 0, 360, 360,0.000000 }, - {2251,2251, 60, 0, 306, 306,0.000000 }, - {2252,2252, 66, 0, 93, 93,0.000000 }, - {2253,2253, 60, 0, 313, 313,0.000000 }, - {2249,2249, 64, 0, 300, 300,0.000000 }, - {2254,2254, 60, 0, 40, 40,0.000000 }, - {2255,2255, 60, 0, 26, 26,0.000000 }, - {2256,2256, 56, 0, 106, 106,0.000000 }, - {2257,2257, 53, 0, 313, 313,0.000000 }, - {2258,2258, 60, 0, 60, 60,0.000000 }, - {2259,2259, 48, 0, 180, 180,0.000000 }, - {2260,2260, 67, 0, 80, 80,0.000000 }, - {2261,2261, 60, 0, 320, 320,0.000000 }, - {2261,2261, 72, 0, 246, 246,0.000000 }, - {2262,2262, 60, 0, 40, 40,0.000000 }, - {2263,2263, 0, 0, 593, 593,0.000000 }, - {2264,2264, 24, 0, 13, 13,0.000000 }, - {2265,2265, 36, 0, 26, 26,0.000000 }, - { 343, 343, 36, 0, 26, 26,0.000000 }, - { 347, 347, 0, 0, 66, 66,0.000000 }, - { 347, 347, 12, 0, 53, 53,0.000000 }, - {2266,2266, 12, 0, 60, 60,0.000000 }, - {2267,2267, 24, 0, 20, 20,0.000000 }, - {2267,2267, 36, 0, 13, 13,0.000000 }, - {2268,2268, 0, 0, 66, 66,0.000000 }, - {2266,2266, 24, 0, 20, 20,0.000000 }, - {2269,2269, 88, 0, 920, 920,0.000000 }, - {2270,2270, 88, 0, 486, 486,0.000000 }, - {2271,2271, 13, 0, 100, 100,0.000000 }, - { 351, 351, 0, 0, 73, 73,0.000000 }, - {2271,2271, 15, 0, 113, 113,0.000000 }, - {2272,2272, 0, 0, 1226, 1226,0.000000 }, - {2273,2273, 0, 0, 2193, 2193,0.000000 }, - {2274,2274, 0, 0, 866, 866,0.000000 }, - {2275,2275, 0, 0, 886, 886,0.000000 }, - {2276,2276, 0, 0, 1900, 1900,0.000000 }, - {2277,2277, 0, 0, 266, 266,0.000000 }, - {2278,2278, 0, 0, 313, 313,0.000000 }, - {2279,2279, 0, 0, 40000, 1833,0.000000 }, - {2280,2280, 0, 0, 126, 126,0.000000 }, - {2281,2281, 0, 0, 4580, 4580,0.000000 }, - {2282,2282, 0, 0, 253, 253,0.000000 }, - {2283,2283, 0, 0, 120, 120,0.000000 }, - {2284,2284, 0, 0, 40000, 46,0.000000 }, - {2285,2285, 0, 0, 2320, 13,0.000000 }, - {2286,2286, 0, 0, 80, 60,0.000000 }, - {2287,2287, 0, 0, 400, 400,0.000000 }, - {2288,2288, 0, 0, 1953, 1953,0.000000 }, - {2289,2289, 0, 0, 1446, 1446,0.000000 }, - {2290,2290, 0, 0, 360, 360,0.000000 }, - {2291,2291, 0, 0, 40000, 6,0.000000 }, - {2292,2292, 0, 0, 40000, 6,0.000000 }, - {2293,2293, 0, 0, 2026, 2026,0.000000 }, - {2294,2294, 0, 0, 246, 13,0.000000 }, - {2295,2295, 0, 0, 233, 233,0.000000 }, - {2296,2296, 0, 0, 2600, 1333,0.000000 }, - {2297,2297, 79, 0, 20, 20,0.000000 }, - {2297,2297, 72, 0, 20, 20,0.000000 }, - {2298,2298, 72, 0, 13, 13,0.000000 }, - {2298,2298, 79, 0, 13, 13,0.000000 }, - { 554, 554, 60, 0, 160, 160,0.000000 }, - {2299,2299, 72, 0, 253, 253,0.000000 }, - {2300,2300, 84, 0, 106, 106,0.000000 }, - { 555, 555, 66, 0, 20, 20,0.000000 }, - {2301,2302, 35, 0, 20, 20,0.000000 }, - {2303,2304, 52, 0, 20, 20,0.000000 }, - {2305,1548, 48, 0, 66, 66,0.000000 }, - {1595,1595, 58, 0, 33, 33,0.000000 }, - {2305,1548, 60, 0, 73, 73,0.000000 }, - {2306,2307, 47, 0, 606, 606,0.000000 }, - {2306,2307, 43, 0, 313, 313,0.000000 }, - {2306,2307, 49, 0, 706, 706,0.000000 }, - {2306,2307, 51, 0, 840, 840,0.000000 }, - {2306,2307, 54, 0, 820, 820,0.000000 }, - {2306,2307, 57, 0, 780, 780,0.000000 }, - {2306,2307, 72, 0, 713, 713,0.000000 }, - {2306,2307, 60, 0, 786, 786,0.000000 }, - {2306,2307, 76, 0, 720, 720,0.000000 }, - {2306,2307, 84, 0, 720, 720,0.000000 }, - {2306,2307, 36, 0, 193, 193,0.000000 }, - {1560,2308, 65, 0, 113, 113,0.000000 }, - {2309,2310, 84, 0, 40000, 0,0.000000 }, - {1564,1564, 83, 0, 60, 60,0.000000 }, - { 380, 381, 84, 0, 40000, 0,0.000000 }, - {1568,1568, 24, 0, 40, 40,0.000000 }, - {2306,2307, 77, 0, 713, 713,0.000000 }, - {2311,2312, 60, 0, 86, 86,0.000000 }, - {2313,2314, 65, 0, 160, 160,0.000000 }, - {2315,2315, 59, 0, 13, 13,0.000000 }, - {2316,2316, 51, 0, 40, 40,0.000000 }, - {1612,1612, 45, 0, 46, 46,0.000000 }, - {2317,2317, 71, 0, 133, 133,0.000000 }, - {2318,2318, 60, 0, 153, 153,0.000000 }, - {2319,2319, 58, 0, 40, 40,0.000000 }, - {2320,2320, 53, 0, 40, 40,0.000000 }, - { 397, 397, 64, 0, 86, 86,0.000000 }, - {2321,2321, 71, 0, 13, 13,0.000000 }, - {2322,2322, 61, 0, 326, 326,0.000000 }, - {2323,2323, 61, 0, 640, 640,0.000000 }, - {2324, 392, 44, 0, 80, 80,0.000000 }, - {2324, 393, 40, 0, 40, 40,0.000000 }, - {1595,1595, 69, 0, 20, 20,0.000000 }, - {1595,1595, 68, 0, 20, 20,0.000000 }, - {1595,1595, 63, 0, 33, 33,0.000000 }, - {2325,2326, 74, 0, 200, 200,0.000000 }, - {2327,2328, 60, 0, 340, 340,0.000000 }, - {2329,2330, 80, 0, 113, 113,0.000000 }, - {2331,2332, 64, 0, 500, 500,0.000000 }, - { 397, 397, 72, 0, 73, 73,0.000000 }, - {2333,2334, 78, 0, 806, 806,0.000000 }, - {1608,1609, 82, 0, 353, 353,0.000000 }, - {2315,2315, 48, 0, 13, 13,0.000000 }, - {2316,2316, 53, 0, 40, 40,0.000000 }, - {2335,2335, 0, 0, 546, 546,0.000000 }, - {2336,2337, 0, 0, 546, 546,0.000000 }, - {2338,2339, 0, 0, 40000, 86,0.000000 }, - {2340,2340, 0, 0, 1580, 1580,0.000000 }, - {2341,2341, 0, 0, 1153, 1153,0.000000 }, - {2342,2342, 0, 0, 40000, 220,0.000000 }, - {2343,2343, 0, 0, 40000, 240,0.000000 }, - {2344,2345, 0, 0, 380, 380,0.000000 }, - {2346,2346, 0, 0, 40000, 6,0.000000 }, - {2347,2348, 0, 0, 40000, 20,0.000000 }, - {2349,2350, 0, 0, 40000, 6,0.000000 }, - {2351,2352, 0, 0, 40000, 6,0.000000 }, - {2353,2354, 0, 0, 40000, 20,0.000000 }, - {2355,2356, 0, 0, 40000, 213,0.000000 }, - {2357,2357, 14, 0, 26, 26,0.000000 }, - {2358,2358, 35, 0, 40, 40,0.000000 }, - {2357,2357, 19, 0, 26, 26,0.000000 }, - {2359,2359, 43, 0, 86, 86,0.000000 }, - {2360,2360, 41, 0, 60, 60,0.000000 }, - {2360,2360, 43, 0, 53, 53,0.000000 }, - {2360,2360, 45, 0, 60, 60,0.000000 }, - {2360,2360, 47, 0, 53, 53,0.000000 }, - {2361,2362, 0, 0, 1553, 1553,0.000000 }, - {2363,2363, 0, 0, 1213, 1213,0.000000 }, - {2364,2364, 0, 0, 2280, 2280,0.000000 }, - {2365,2365, 0, 0, 966, 966,0.000000 }, - {2366,2366, 0, 0, 500, 500,0.000000 }, - {2367,2367, 0, 0, 326, 326,0.000000 }, - {2368,2368, 0, 0, 1926, 1926,0.000000 }, - {2369,2369, 0, 0, 520, 520,0.000000 }, - {2370,2370, 0, 0, 993, 993,0.000000 }, - {2371,2371, 0, 0, 1740, 1740,0.000000 }, - {2372,2372, 0, 0, 2300, 80,0.000000 }, - {2373,2373, 0, 0, 513, 513,0.000000 }, - {2374,2374, 0, 0, 40, 40,0.000000 }, - {2375,2375, 0, 0, 1226, 1226,0.000000 }, - {2376,2376, 0, 0, 606, 606,0.000000 }, - {2377,2377, 0, 0, 40000, 6,0.000000 }, - {2378,2378, 0, 0, 993, 6,0.000000 }, - {2379,2379, 0, 0, 40000, 153,0.000000 }, - {2380,2380, 0, 0, 40000, 6,0.000000 }, - {2381,2381, 0, 0, 40000, 0,0.000000 }, - {2382,2382, 0, 0, 40000, 6,0.000000 }, - {2383,2383, 0, 0, 40000, 6,0.000000 }, - {2384,2384, 0, 0, 40000, 6,0.000000 }, - {2385,2385, 0, 0, 273, 273,0.000000 }, - {2386,2386, 0, 0, 1580, 1580,0.000000 }, - {2387,2387, 0, 0, 140, 140,0.000000 }, - { 402, 402, 0, 0, 146, 146,0.000000 }, - {2388,2388, 0, 0, 40000, 446,0.000000 }, - {2389,2389, 0, 0, 2006, 2006,0.000000 }, - {2390,2390, 0, 0, 353, 353,0.000000 }, - {2391,2391, 0, 0, 233, 233,0.000000 }, - {2392,2392, 0, 0, 226, 226,0.000000 }, - {2393,2393, 0, 0, 853, 853,0.000000 }, - {2394,2394, 0, 0, 100, 100,0.000000 }, - {2395,2395, 0, 0, 40000, 40,0.000000 }, - {2396,2397, 0, 0, 633, 20,0.000000 }, - {2398,2398, 0, 0, 40, 40,0.000000 }, - {2399,2400, 0, 0, 493, 493,0.000000 }, - {2401,2401, 0, 0, 40000, 86,0.000000 }, - {2402,2402, 0, 0, 40000, 0,0.000000 }, - {2403,2404, 0, 0, 40000, 66,0.000000 }, - {2405,2406, 0, 0, 186, 46,0.000000 }, - {2407,2408, 0, 0, 40000, 6,0.000000 }, - {2409,2409, 0, 0, 1153, 1153,0.000000 }, - {2410,2410, 0, 0, 40000, 0,0.000000 }, - {2411,2411, 0, 0, 86, 86,0.000000 }, - {2412,2413, 0, 0, 40000, 73,0.000000 }, - {2414,2414, 0, 0, 40000, 40,0.000000 }, - {2415,2416, 0, 0, 40000, 286,0.000000 }, - {2417,2418, 0, 0, 40000, 20,0.000000 }, - {2419,2420, 0, 0, 600, 600,0.000000 }, - {2421,2422, 0, 0, 253, 253,0.000000 }, - {2423,2424, 0, 0, 466, 466,0.000000 }, - {2425,2426, 0, 0, 40000, 6,0.000000 }, - {2427,2427, 33, 0, 53, 53,0.000000 }, - {2428,2429, 38, 0, 46, 46,0.000000 }, - {2430,2430, 38, 0, 13, 13,0.000000 }, - {2431,2431, 38, 0, 86, 86,0.000000 }, - {2432,2432, 40, 0, 6, 6,0.000000 }, - {2433,2434, 41, 0, 60, 60,0.000000 }, - {2435,2435, 0, 0, 20, 20,0.000000 }, - {2435,2435, 41, 0, 26, 26,0.000000 }, - {2360,2360, 48, 0, 53, 53,0.000000 }, - {2436,2436, 17, 0, 446, 446,0.000000 }, - {2360,2360, 50, 0, 46, 46,0.000000 }, - {2435,2435, 45, 0, 20, 20,0.000000 }, - {2437,2437,254, 0, 26, 26,0.000000 }, - {2438,2438, 60, 0, 80, 80,0.000000 }, - {2439,2439, 56, 0, 80, 80,0.000000 }, - {2440,2440, 60, 0, 40, 40,0.000000 }, - {2440,2440, 55, 0, 40, 40,0.000000 }, - {2441,2441, 63, 0, 86, 86,0.000000 }, - {2442,2442, 57, 0, 40, 40,0.000000 }, - {2443,2443, 0, 0, 40000, 106,0.000000 }, - {2444,2444, 0, 0, 246, 246,0.000000 }, - {2445,2445, 0, 0, 3133, 13,0.000000 }, - {2446,2446, 0, 0, 40000, 153,0.000000 }, - {2447,2447, 0, 0, 40000, 480,0.000000 }, - {2448,2448, 0, 0, 40000, 73,0.000000 }, - {2449,2449, 0, 0, 40000, 526,0.000000 }, - {2450,2450, 0, 0, 40000, 146,0.000000 }, - {2451,2451, 0, 0, 4520, 4520,0.000000 }, - {2452,2452, 0, 0, 280, 280,0.000000 }, - { 752, 752, 55, 0, 46, 46,0.000000 }, - {2453,2453, 0, 0, 646, 646,0.000000 }, - {2454,2454, 0, 0, 600, 600,0.000000 }, - {2455,2455, 0, 0, 86, 86,0.000000 }, - {2456,2456, 0, 0, 386, 386,0.000000 }, - {2457,2457, 0, 0, 40000, 0,0.000000 }, - {2458,2458, 0, 0, 1340, 1340,0.000000 }, - {2459,2459, 0, 0, 786, 786,0.000000 }, - {2460,2460, 0, 0, 680, 680,0.000000 }, - {2461,2461, 0, 0, 2113, 2113,0.000000 }, - {2462,2462, 0, 0, 3193, 13,0.000000 }, - {2463,2463, 0, 0, 726, 726,0.000000 }, - { 884, 884, 0, 0, 46, 46,0.000000 }, - { 884, 884, 28, 0, 100, 100,0.000000 }, - {2464,2464, 29, 0, 66, 66,0.000000 }, - { 886, 886, 31, 0, 20, 20,0.000000 }, - { 360, 360, 32, 0, 46, 46,0.000000 }, - { 361, 361, 33, 0, 100, 100,0.000000 }, - {2453,2453, 34, 0, 760, 760,0.000000 }, - { 888, 888, 29, 0, 46, 46,0.000000 }, - { 886, 886, 55, 0, 13, 13,0.000000 }, - { 890, 890, 48, 0, 73, 73,0.000000 }, - { 884, 884, 58, 0, 40, 40,0.000000 }, - {2465,2465, 45, 0, 46, 46,0.000000 }, - {2465,2465, 43, 0, 46, 46,0.000000 }, - {2466,2466, 73, 0, 520, 520,0.000000 }, - {2467,2467, 72, 0, 266, 266,0.000000 }, - {2468,2468, 76, 0, 160, 160,0.000000 }, - {2467,2467, 84, 0, 273, 273,0.000000 }, - {2468,2468, 36, 0, 166, 166,0.000000 }, - {2469,2469, 65, 0, 86, 86,0.000000 }, - {2470,2470, 83, 0, 73, 73,0.000000 }, - {2471,2471, 50, 0, 300, 300,0.000000 }, - {2468,2468, 77, 0, 133, 133,0.000000 }, - { 897, 897, 55, 0, 33, 33,0.000000 }, - {2472,2472, 60, 0, 46, 46,0.000000 }, - { 897, 897, 50, 0, 33, 33,0.000000 }, - {2473,2473, 42, 0, 206, 206,0.000000 }, - {2473,2473, 46, 0, 166, 166,0.000000 }, - {2474,2474, 71, 0, 133, 133,0.000000 }, - {2474,2474, 60, 0, 160, 160,0.000000 }, - {2455,2455, 58, 0, 66, 66,0.000000 }, - {2455,2455, 53, 0, 86, 86,0.000000 }, - {2475,2475, 91, 0, 40, 40,0.000000 }, - {2476,2476, 61, 0, 140, 140,0.000000 }, - {2477,2477, 61, 0, 786, 786,0.000000 }, - {2478,2478, 44, 0, 33, 33,0.000000 }, - {2479,2479, 40, 0, 840, 840,0.000000 }, - {2480,2480, 69, 0, 40, 40,0.000000 }, - { 361, 361, 68, 0, 40, 40,0.000000 }, - { 361, 361, 63, 0, 60, 60,0.000000 }, - {2481,2481, 74, 0, 73, 73,0.000000 }, - {2482,2482, 60, 0, 73, 73,0.000000 }, - { 908, 908, 80, 0, 33, 33,0.000000 }, - {2483,2483, 64, 0, 306, 306,0.000000 }, - {2483,2483, 73, 0, 260, 260,0.000000 }, - {2483,2483, 70, 0, 260, 260,0.000000 }, - { 886, 886, 68, 0, 6, 6,0.000000 }, - { 886, 886, 48, 0, 13, 13,0.000000 }, - {2484,2484, 0, 0, 440, 440,0.000000 }, - {2485,2485, 0, 0, 253, 253,0.000000 }, - {2486,2486, 0, 0, 306, 306,0.000000 }, - {2487,2487, 0, 0, 1213, 1213,0.000000 }, - {2488,2488, 0, 0, 626, 626,0.000000 }, - {2489,2489, 0, 0, 40000, 206,0.000000 }, - {2490,2490, 0, 0, 40000, 100,0.000000 }, - {2491,2491, 0, 0, 40000, 13,0.000000 }, - {2492,2492, 0, 0, 2273, 2273,0.000000 }, - {2493,2493, 0, 0, 1740, 1740,0.000000 }, - {2494,2494, 0, 0, 1953, 1953,0.000000 }, - {2495,2495, 0, 0, 1740, 1740,0.000000 }, - {2496,2496, 0, 0, 386, 386,0.000000 }, - {2497,2497, 0, 0, 233, 233,0.000000 }, - {2498,2498, 0, 0, 40000, 106,0.000000 }, - {2499,2499, 0, 0, 40000, 13,0.000000 }, - {2500,2500, 0, 0, 40000, 0,0.000000 }, - {2501,2501, 0, 0, 40000, 186,0.000000 }, - {2502,2502, 0, 0, 66, 66,0.000000 }, - {2503,2503, 0, 0, 46, 46,0.000000 }, - {2504,2504, 0, 0, 40000, 186,0.000000 }, - {2505,2505, 0, 0, 1106, 1106,0.000000 }, - {2506,2506, 0, 0, 40000, 186,0.000000 }, - {2507,2507, 0, 0, 40000, 100,0.000000 }, - {2508,2508, 0, 0, 40000, 206,0.000000 }, - {2509,2509, 0, 0, 40000, 60,0.000000 }, - {2510,2510, 0, 0, 40000, 106,0.000000 }, - {2511,2511, 0, 0, 60, 60,0.000000 }, - {2512,2512, 0, 0, 40, 40,0.000000 }, - {2513,2513, 0, 0, 1833, 26,0.000000 }, - {2514,2514, 0, 0, 806, 806,0.000000 }, - {2515,2515, 0, 0, 1106, 1106,0.000000 }, - {2516,2516, 0, 0, 40000, 6,0.000000 }, - {2517,2517, 0, 0, 40000, 180,0.000000 }, - {2518,2518, 0, 0, 40000, 340,0.000000 }, - {2519,2519, 0, 0, 1873, 6,0.000000 }, - {2520,2520, 0, 0, 2586, 2586,0.000000 }, - {2521,2521, 0, 0, 1740, 1740,0.000000 }, - {2522,2522, 0, 0, 3493, 13,0.000000 }, - {2523,2523, 0, 0, 40000, 266,0.000000 }, - {2524,2524, 0, 0, 6160, 33,0.000000 }, - {2525,2525, 0, 0, 40000, 46,0.000000 }, - {2526,2526, 0, 0, 1140, 1140,0.000000 }, - { 346, 346, 30, 0, 46, 46,0.000000 }, - { 346, 346, 31, 0, 33, 33,0.000000 }, - { 346, 346, 32, 0, 40, 40,0.000000 }, - { 346, 346, 33, 0, 46, 46,0.000000 }, - { 346, 346, 34, 0, 53, 53,0.000000 }, - { 346, 346, 35, 0, 33, 33,0.000000 }, - { 346, 346, 37, 0, 146, 146,0.000000 }, - { 346, 346, 39, 0, 186, 186,0.000000 }, - { 346, 346, 41, 0, 206, 206,0.000000 }, - { 346, 346, 43, 0, 133, 133,0.000000 }, - { 346, 346, 45, 0, 126, 126,0.000000 }, - { 346, 346, 47, 0, 153, 153,0.000000 }, - { 346, 346, 48, 0, 153, 153,0.000000 }, - { 346, 346, 49, 0, 153, 153,0.000000 }, - { 512, 512, 84, 0, 73, 73,0.000000 }, - {2206,2206, 84, 0, 140, 140,0.000000 }, - {2527,2527, 55, 0, 13, 13,0.000000 }, - {2528,2528, 36, 0, 20, 20,0.000000 }, - {2529,2529, 38, 0, 66, 66,0.000000 }, - {2530,2530, 60, 0, 86, 86,0.000000 }, - {2531,2531, 38, 0, 60, 60,0.000000 }, - {2532,2532, 17, 0, 2233, 2233,0.000000 }, - {2532,2532, 18, 0, 2266, 2266,0.000000 }, - {2532,2532, 19, 0, 2280, 2280,0.000000 }, - {2532,2532, 20, 0, 46, 46,0.000000 }, - {2532,2532, 21, 0, 46, 46,0.000000 }, - {2532,2532, 22, 0, 40, 40,0.000000 }, - {2532,2532, 23, 0, 53, 53,0.000000 }, - {2532,2532, 24, 0, 100, 100,0.000000 }, - {2532,2532, 25, 0, 46, 46,0.000000 }, - {2532,2532, 26, 0, 60, 60,0.000000 }, - {2532,2532, 27, 0, 40, 40,0.000000 }, - {2532,2532, 28, 0, 53, 53,0.000000 }, - {2532,2532, 29, 0, 126, 126,0.000000 }, - {2533,2533, 84, 0, 133, 133,0.000000 }, - {2534,2534, 48, 0, 86, 86,0.000000 }, - {2535,2535, 65, 0, 486, 486,0.000000 }, - {2536,2536, 65, 0, 526, 526,0.000000 }, - {2537,2537, 55, 0, 66, 66,0.000000 }, - {2537,2537, 41, 0, 60, 60,0.000000 }, - { 346, 346, 63, 0, 106, 106,0.000000 }, - { 346, 346, 55, 0, 106, 106,0.000000 }, - {2538,2538, 55, 0, 1200, 1200,0.000000 }, - {2538,2538, 53, 0, 1206, 1206,0.000000 }, - {2534,2534, 50, 0, 86, 86,0.000000 }, - { 506, 506, 84, 0, 133, 133,0.000000 }, - { 506, 506, 74, 0, 133, 133,0.000000 }, - { 504, 504, 84, 0, 473, 473,0.000000 }, - { 504, 504, 74, 0, 486, 486,0.000000 }, - {2539,2539, 84, 0, 133, 133,0.000000 }, - {2540,2540, 74, 0, 20, 20,0.000000 }, - {1911,1911, 48, 0, 46, 46,0.000000 }, - {1911,1911, 36, 0, 20, 20,0.000000 }, - {2541,2541, 74, 0, 133, 133,0.000000 }, - {2542,2542, 0, 0, 613, 613,0.000000 }, - {2543,2543, 0, 0, 40000, 480,0.000000 }, - {2544,2544, 0, 0, 1133, 1133,0.000000 }, - {2545,2545, 0, 0, 1200, 1200,0.000000 }, - {2546,2547, 0, 0, 1313, 1313,0.000000 }, - {2548,2549, 0, 0, 40000, 6,0.000000 }, - {2550,2550, 0, 0, 1740, 1740,0.000000 }, - {2551,2552, 0, 0, 860, 860,0.000000 }, - {2553,2553, 0, 0, 40000, 0,0.000000 }, - {2554,2554, 0, 0, 2300, 2300,0.000000 }, - {2555,2556, 0, 0, 40000, 0,0.000000 }, - {2557,2557, 0, 0, 506, 13,0.000000 }, - {2558,1467, 0, 0, 40000, 6,0.000000 }, - {2559,2560, 0, 0, 40000, 0,0.000000 }, - {2561,2561, 0, 0, 40000, 106,0.000000 }, - {2562,2562, 0, 0, 1013, 1013,0.000000 }, - {2563,2564, 0, 0, 1020, 1020,0.000000 }, - {2565,2565, 0, 0, 1746, 1746,0.000000 }, - {2566,2567, 0, 0, 1446, 1446,0.000000 }, - {2568,2568, 0, 0, 826, 826,0.000000 }, - {2569,2569, 0, 0, 2293, 2293,0.000000 }, - {2570,2570, 0, 0, 2386, 2386,0.000000 }, - {2571,2572, 0, 0, 40000, 46,0.000000 }, - {2573,2574, 0, 0, 40000, 26,0.000000 }, - {2575,2575, 0, 0, 40000, 126,0.000000 }, - { 229,2576, 0, 0, 1893, 13,0.000000 }, - {2577,2577, 0, 0, 1046, 1046,0.000000 }, - { 239,2578, 0, 0, 40000, 53,0.000000 }, - {2579,2579, 0, 0, 40000, 13,0.000000 }, - {2580,2580, 0, 0, 40000, 66,0.000000 }, - {2581,2582, 0, 0, 3466, 3466,0.000000 }, - {2583,2584, 0, 0, 233, 233,0.000000 }, - {2585,2586, 0, 0, 40000, 0,0.000000 }, - {2587,2588, 0, 0, 40000, 0,0.000000 }, - {2589,2589, 0, 0, 40000, 6,0.000000 }, - {2590,2590, 0, 0, 40000, 6,0.000000 }, - {2591,2592, 0, 0, 40000, 0,0.000000 }, - {2593,2594, 0, 0, 680, 0,0.000000 }, - {2595,2595, 0, 0, 40000, 0,0.000000 }, - {2596,2597, 0, 0, 40000, 6,0.000000 }, - {2598,2599, 0, 0, 40000, 0,0.000000 }, - {2600,2601, 0, 0, 40000, 13,0.000000 }, - {2602,2602, 0, 0, 5093, 5093,0.000000 }, - {2603,2603, 0, 0, 40000, 6,0.000000 }, - {2604,2604, 0, 0, 40000, 40,0.000000 }, - {2605,2606, 0, 0, 40000, 0,0.000000 }, - {2607,2607, 0, 0, 40000, 0,0.000000 }, - {2608,2609, 0, 0, 40000, 6,0.000000 }, - {2610,2610, 0, 0, 40000, 20,0.000000 }, - {2611,2611, 0, 0, 40000, 6,0.000000 }, - {2612,2612, 0, 0, 2253, 2253,0.000000 }, - {2613,2613, 0, 0, 973, 973,0.000000 }, - {2614,2615, 0, 0, 40000, 6,0.000000 }, - {2616,2617, 0, 0, 40000, 6,0.000000 }, - {2618,2619, 0, 0, 353, 353,0.000000 }, - {2620,2621, 0, 0, 40000, 500,0.000000 }, - {2622,2623, 0, 0, 40000, 26,0.000000 }, - {2624,2625, 0, 0, 40000, 53,0.000000 }, - {2626,2627, 0, 0, 4026, 13,0.000000 }, - {2628,2629, 0, 0, 3400, 13,0.000000 }, - {1516,2630, 0, 0, 226, 226,0.000000 }, - {2631,2632, 0, 0, 40000, 193,0.000000 }, - {2633,2633, 0, 0, 2380, 2380,0.000000 }, - {2634,2635, 0, 0, 40000, 373,0.000000 }, - {2636,2636, 0, 0, 40000, 133,0.000000 }, - {2637,2637, 0, 0, 280, 280,0.000000 }, - {2638,2639, 0, 0, 273, 273,0.000000 }, - {2640,2641, 0, 0, 3333, 3333,0.000000 }, - {2642,2642, 0, 0, 40000, 266,0.000000 }, - {2643,2644, 0, 0, 166, 166,0.000000 }, - {2645,2645, 0, 0, 40000, 6,0.000000 }, - {2646,2647, 0, 0, 40000, 0,0.000000 }, - {2648,2648, 0, 0, 586, 586,0.000000 }, - {2649,2649, 0, 0, 1660, 86,0.000000 }, - {2650,2651, 0, 0, 440, 440,0.000000 }, - {2652,2652, 0, 0, 40000, 113,0.000000 }, - {2653,2654, 0, 0, 40000, 6,0.000000 }, - {2655,2656, 0, 0, 1766, 1766,0.000000 }, - {2657,2657, 0, 0, 40000, 0,0.000000 }, - {2658,2658, 35, 0, 20, 20,0.000000 }, - {2659,2659, 35, 0, 26, 26,0.000000 }, - {2660,2660, 52, 0, 20, 20,0.000000 }, - {2661,2661, 60, 0, 80, 80,0.000000 }, - {2662,2662, 58, 0, 20, 20,0.000000 }, - {2663,2663, 60, 0, 113, 113,0.000000 }, - {2664,2664, 50, 0, 433, 433,0.000000 }, - {2665,2665, 43, 0, 40, 40,0.000000 }, - {2664,2664, 55, 0, 513, 513,0.000000 }, - {1553,1553, 43, 0, 26, 26,0.000000 }, - {2666,2666, 50, 0, 173, 173,0.000000 }, - {2667,2667, 43, 0, 173, 173,0.000000 }, - {2666,2666, 53, 0, 40, 40,0.000000 }, - {2666,2666, 57, 0, 186, 186,0.000000 }, - {2668,2668, 72, 0, 260, 260,0.000000 }, - {2666,2666, 60, 0, 220, 220,0.000000 }, - { 373, 373, 76, 0, 260, 260,0.000000 }, - {2669,2669, 84, 0, 213, 213,0.000000 }, - {2670,2670, 42, 0, 406, 406,0.000000 }, - {2671,2671, 65, 0, 86, 86,0.000000 }, - {2672,2672, 84, 0, 113, 113,0.000000 }, - {2673,2673, 84, 0, 426, 426,0.000000 }, - {2674,2674, 24, 0, 46, 46,0.000000 }, - { 383, 383, 77, 0, 246, 246,0.000000 }, - {2675,2675, 58, 0, 153, 153,0.000000 }, - {2676,2676, 53, 0, 153, 153,0.000000 }, - {2677,2677, 64, 0, 73, 73,0.000000 }, - {2678,2678, 71, 0, 26, 26,0.000000 }, - {2679,2679, 44, 0, 606, 606,0.000000 }, - {2680,2680, 40, 0, 366, 366,0.000000 }, - {2681,2681, 69, 0, 20, 20,0.000000 }, - {2682,2682, 60, 0, 360, 360,0.000000 }, - {2683,2683, 80, 0, 60, 60,0.000000 }, - {2684,2684, 64, 0, 873, 873,0.000000 }, - {2685,2685, 72, 0, 33, 33,0.000000 }, - {2686,2686, 70, 0, 273, 273,0.000000 }, - {2687,2687, 48, 0, 40, 40,0.000000 }, - {2688,2688, 53, 0, 213, 213,0.000000 }, - {2689,2690, 0, 0, 40000, 140,0.000000 }, - {2691,2692, 0, 0, 626, 626,0.000000 }, - {2693,2694, 0, 0, 40000, 0,0.000000 }, - {2695,2696, 0, 0, 2213, 2213,0.000000 }, - {2697,2698, 0, 0, 4140, 0,0.000000 }, - { 192,2699, 0, 0, 40000, 6,0.000000 }, - {2700,2701, 0, 0, 153, 153,0.000000 }, - {2702,2703, 0, 0, 253, 253,0.000000 }, - {2704,2705, 0, 0, 40000, 0,0.000000 }, - {2706,2707, 0, 0, 40000, 6,0.000000 }, - {2708,2709, 0, 0, 40000, 6,0.000000 }, - {2710,2711, 0, 0, 440, 440,0.000000 }, - {2712,1473, 0, 0, 213, 213,0.000000 }, - {2713,2714, 0, 0, 120, 120,0.000000 }, - {2715,2716, 0, 0, 140, 140,0.000000 }, - {1478,2717, 0, 0, 40000, 113,0.000000 }, - {2718,2719, 0, 0, 40000, 6,0.000000 }, - { 286,2720, 0, 0, 40000, 20,0.000000 }, - {2721,2722, 0, 0, 40000, 13,0.000000 }, - {2723,2724, 0, 0, 40000, 0,0.000000 }, - {2725,2726, 0, 0, 526, 526,0.000000 }, - {2727,2724, 0, 0, 40000, 0,0.000000 }, - {1514,2728, 0, 0, 40000, 53,0.000000 }, - {2729,2730, 0, 0, 186, 186,0.000000 }, - {2731,2732, 0, 0, 226, 226,0.000000 }, - {2733,2734, 0, 0, 266, 266,0.000000 }, - {2735,2736, 0, 0, 80, 80,0.000000 }, - {2737,2738, 0, 0, 40000, 0,0.000000 }, - {2739,2740, 0, 0, 260, 260,0.000000 }, - {2741,2742, 0, 0, 286, 286,0.000000 }, - {2743,2744, 0, 0, 193, 193,0.000000 }, - {2745,2746, 0, 0, 40000, 0,0.000000 }, - {2747,2747, 35, 0, 20, 20,0.000000 }, - {2748,2748, 60, 0, 153, 153,0.000000 }, - {2749,2749, 43, 0, 20, 20,0.000000 }, - {2750,2750, 0, 0, 626, 626,0.000000 }, - {2751,2752, 0, 0, 1553, 1553,0.000000 }, - {2753,2754, 0, 0, 1386, 1386,0.000000 }, - {2755,2756, 0, 0, 2026, 2026,0.000000 }, - {2757,2758, 0, 0, 1020, 1020,0.000000 }, - {2759,2760, 0, 0, 2486, 2486,0.000000 }, - {2761,2762, 0, 0, 2880, 2880,0.000000 }, - {2763,2764, 0, 0, 2346, 2346,0.000000 }, - {2765,2766, 0, 0, 40000, 0,0.000000 }, - {2767,2768, 0, 0, 40000, 100,0.000000 }, - {2769,2770, 0, 0, 40000, 13,0.000000 }, - {2771,2772, 0, 0, 40000, 6,0.000000 }, - {2773,2774, 0, 0, 40000, 0,0.000000 }, - {2775,2776, 0, 0, 40000, 13,0.000000 }, - {2777,2778, 0, 0, 40000, 0,0.000000 }, - {2779,2780, 0, 0, 40000, 6,0.000000 }, - {2781,2782, 0, 0, 40000, 6,0.000000 }, - {2783,2784, 0, 0, 913, 913,0.000000 }, - {2785,2786, 0, 0, 1653, 1653,0.000000 }, - {2787,2788, 0, 0, 40000, 153,0.000000 }, - {2789,2790, 0, 0, 1273, 1273,0.000000 }, - {2791,2792, 0, 0, 1166, 1166,0.000000 }, - {2793,2794, 0, 0, 386, 386,0.000000 }, - {2795,2796, 0, 0, 40000, 1993,0.000000 }, - {2795,2797, 0, 0, 2526, 1333,0.000000 }, - {2798,2799, 0, 0, 166, 6,0.000000 }, - {2800,2801, 0, 0, 13080, 213,0.000000 }, - {2802,2803, 0, 0, 40000, 6,0.000000 }, - {2804,2805, 0, 0, 40000, 6,0.000000 }, - {2806,2807, 0, 0, 493, 493,0.000000 }, - {2808,2809, 0, 0, 126, 6,0.000000 }, - {2810,2811, 0, 0, 80, 80,0.000000 }, - {2812,2813, 0, 0, 380, 380,0.000000 }, - {2814,2815, 0, 0, 2506, 2506,0.000000 }, - {2816,2817, 0, 0, 2186, 2186,0.000000 }, - {2818,2819, 0, 0, 2520, 2520,0.000000 }, - {2820,2821, 0, 0, 440, 440,0.000000 }, - {2822,2823, 0, 0, 106, 106,0.000000 }, - {2824,2825, 0, 0, 1933, 1933,0.000000 }, - {2826,2827, 0, 0, 40000, 6,0.000000 }, - {2828,2829, 0, 0, 1933, 1933,0.000000 }, - {2830,2831, 0, 0, 546, 546,0.000000 }, - {2832,2833, 0, 0, 973, 973,0.000000 }, - {2834,2835, 0, 0, 586, 26,0.000000 }, - {2836,2837, 0, 0, 786, 786,0.000000 }, - {2838,2839, 0, 0, 1920, 1920,0.000000 }, - {2840,2841, 0, 0, 333, 333,0.000000 }, - {2842,2843, 0, 0, 1120, 1120,0.000000 }, - {2844,2845, 0, 0, 40000, 153,0.000000 }, - {2846,2847, 0, 0, 40000, 153,0.000000 }, - {2848,2849, 0, 0, 40000, 153,0.000000 }, - {2850,2851, 0, 0, 40000, 213,0.000000 }, - {2852,2853, 0, 0, 40000, 240,0.000000 }, - {2854,2855, 0, 0, 40000, 93,0.000000 }, - {2856,2856, 0, 0, 333, 333,0.000000 }, - {2857,2857, 0, 0, 333, 333,0.000000 }, - {2858,2859, 0, 0, 866, 866,0.000000 }, - {2860,2861, 0, 0, 40000, 180,0.000000 }, - {2862,2863, 0, 0, 866, 866,0.000000 }, - {2864,2865, 0, 0, 40000, 6,0.000000 }, - {2866,2867, 0, 0, 946, 946,0.000000 }, - {2868,2869, 0, 0, 906, 906,0.000000 }, - {2870,2871, 0, 0, 846, 846,0.000000 }, - {2872,2873, 0, 0, 160, 160,0.000000 }, - {2874,2875, 0, 0, 586, 6,0.000000 }, - {2876,2877, 0, 0, 160, 160,0.000000 }, - {2878,2879, 0, 0, 760, 760,0.000000 }, - {2880,2881, 0, 0, 1193, 1193,0.000000 }, - {2882,2883, 0, 0, 493, 493,0.000000 }, - {2884,2885, 0, 0, 893, 893,0.000000 }, - {2886,2887, 0, 0, 40000, 0,0.000000 }, - {2888,2888, 0, 0, 4413, 4413,0.000000 }, - {2889,2889, 0, 0, 4193, 4193,0.000000 }, - {2890,2890, 0, 0, 3946, 3946,0.000000 }, - {2891,2892, 0, 0, 40000, 26,0.000000 }, - {2893,2893, 0, 0, 60, 60,0.000000 }, - {2894,2894, 0, 0, 40, 40,0.000000 }, - {2895,2895, 0, 0, 1773, 1773,0.000000 }, - {2896,2897, 0, 0, 40000, 6,0.000000 }, - {2898,2899, 0, 0, 1073, 6,0.000000 }, - {2353,2900, 0, 0, 4800, 4800,0.000000 }, - {2901,2901, 0, 0, 126, 126,0.000000 }, - {2902,2903, 0, 0, 40000, 20,0.000000 }, - {2904,2905, 0, 0, 40000, 20,0.000000 }, - {2906,2907, 0, 0, 40000, 6,0.000000 }, - {2908,2909, 0, 0, 4546, 4546,0.000000 }, - {2910,2911, 0, 0, 40000, 6,0.000000 }, - {2912,2912, 0, 0, 913, 913,0.000000 }, - {2913,2914, 0, 0, 486, 486,0.000000 }, - {2915,2916, 0, 0, 1740, 1740,0.000000 }, - {2917,2918, 0, 0, 1726, 1726,0.000000 }, - {2919,2920, 0, 0, 1740, 1740,0.000000 }, - {2921,2922, 0, 0, 1420, 1420,0.000000 }, - {2923,2924, 0, 0, 546, 546,0.000000 }, - {2925,2926, 0, 0, 513, 513,0.000000 }, - {2927,2928, 0, 0, 226, 226,0.000000 }, - {2929,2929, 0, 0, 40000, 73,0.000000 }, - {2930,2931, 0, 0, 40000, 33,0.000000 }, - {2932,2933, 0, 0, 40000, 6,0.000000 }, - {2934,2935, 0, 0, 40000, 20,0.000000 }, - {2936,2937, 0, 0, 40000, 13,0.000000 }, - {2938,2939, 0, 0, 40000, 106,0.000000 }, - {2940,2940, 0, 0, 40, 40,0.000000 }, - {2941,2941, 0, 0, 40000, 86,0.000000 }, - {2942,2943, 0, 0, 293, 293,0.000000 }, - {2944,2944, 0, 0, 53, 53,0.000000 }, - {2945,2945, 0, 0, 260, 260,0.000000 }, - {2946,2947, 0, 0, 1026, 1026,0.000000 }, - {2948,2948, 0, 0, 40000, 120,0.000000 }, - {2949,2949, 0, 0, 280, 280,0.000000 }, - {2950,2951, 0, 0, 3926, 3926,0.000000 }, - {2952,2953, 0, 0, 6373, 206,0.000000 }, - {2954,2954, 60, 0, 40000, 0,0.000000 }, - {2955,2956, 0, 0, 40000, 153,0.000000 }, - {2957,2958, 0, 0, 40000, 6,0.000000 }, - {2959,2960, 0, 0, 40000, 26,0.000000 }, - {2961,2962, 0, 0, 700, 140,0.000000 }, - {2963,2963, 0, 0, 506, 506,0.000000 }, - {2964,2964, 0, 0, 40000, 680,0.000000 }, - {2436,2436, 49, 0, 593, 593,0.000000 }, - {2357,2357, 61, 0, 26, 26,0.000000 }, - {2357,2357, 56, 0, 26, 26,0.000000 }, - {2357,2357, 58, 0, 26, 26,0.000000 }, - {2357,2357, 49, 0, 33, 33,0.000000 }, - {2357,2357, 44, 0, 26, 26,0.000000 }, - {2965,2965, 0, 0, 40000, 186,0.000000 }, - {2966,2966, 0, 0, 186, 186,0.000000 }, - {2967,2967, 0, 0, 1793, 1793,0.000000 }, - {2968,2968, 0, 0, 40000, 53,0.000000 }, - {2969,2969, 0, 0, 80, 80,0.000000 }, - {2970,2970, 84, 0, 40, 40,0.000000 }, - {2971,2971, 72, 0, 140, 140,0.000000 }, - {2972,2972, 0, 0, 2080, 2080,0.000000 }, - {2973,2973, 0, 0, 40000, 66,0.000000 }, - {2974,2974, 0, 0, 40000, 2100,0.000000 }, - {2975,2975, 0, 0, 1766, 1766,0.000000 }, - {2976,2976, 0, 0, 120, 120,0.000000 }, - {2977,2977, 0, 0, 40000, 0,0.000000 }, - {2978,2978, 0, 0, 40000, 66,0.000000 }, - {2979,2979, 0, 0, 40000, 73,0.000000 }, - {2980,2980, 0, 0, 40000, 126,0.000000 }, - {2981,2981, 0, 0, 40000, 506,0.000000 }, - {2982,2982, 0, 0, 40000, 373,0.000000 }, - {2983,2983, 0, 0, 920, 920,0.000000 }, - {2984,2984, 0, 0, 1106, 1106,0.000000 }, - {2985,2985, 0, 0, 40000, 0,0.000000 }, - {2986,2986, 0, 0, 40000, 0,0.000000 }, - {2987,2987, 0, 0, 40000, 0,0.000000 }, - {2988,2988, 0, 0, 40000, 140,0.000000 }, - {2989,2989, 0, 0, 726, 726,0.000000 }, - {2990,2990, 0, 0, 573, 573,0.000000 }, - {2991,2991, 0, 0, 40000, 146,0.000000 }, - {2992,2992, 0, 0, 40000, 66,0.000000 }, - {2993,2993, 0, 0, 146, 146,0.000000 }, - {2994,2994, 0, 0, 1380, 1380,0.000000 }, - {2995,2995, 0, 0, 40000, 113,0.000000 }, - {2996,2996, 0, 0, 1140, 1140,0.000000 }, - {2997,2997, 0, 0, 1180, 1180,0.000000 }, - {2998,2998, 0, 0, 40000, 0,0.000000 }, - {2999,2999, 0, 0, 40000, 13,0.000000 }, - {3000,3000, 0, 0, 193, 193,0.000000 }, - {3001,3001, 0, 0, 40000, 0,0.000000 }, - {3002,3002, 0, 0, 40000, 433,0.000000 }, - {3003,3003, 0, 0, 1206, 1206,0.000000 }, - {3004,3004, 0, 0, 40000, 480,0.000000 }, - {3005,3005, 0, 0, 40000, 0,0.000000 }, - {3006,3006, 0, 0, 126, 126,0.000000 }, - {3007,3007, 0, 0, 333, 333,0.000000 }, - { 350, 350, 0, 0, 66, 66,0.000000 }, - {3008,3008, 0, 0, 46, 46,0.000000 }, - {3009,3009, 0, 0, 26, 26,0.000000 }, - {3010,3010, 0, 0, 320, 320,0.000000 }, - {3011,3011, 0, 0, 2380, 2380,0.000000 }, - {3012,3012, 0, 0, 180, 180,0.000000 }, - {3013,3013, 0, 0, 260, 260,0.000000 }, - {3014,3014, 0, 0, 40000, 6,0.000000 }, - {3015,3015, 0, 0, 40000, 146,0.000000 }, - { 350, 350, 36, 0, 86, 86,0.000000 }, - { 369, 369, 37, 0, 33, 33,0.000000 }, - {3008,3008, 38, 0, 53, 53,0.000000 }, - { 369, 369, 24, 0, 33, 33,0.000000 }, - {3008,3008, 32, 0, 60, 60,0.000000 }, - { 369, 369, 48, 0, 33, 33,0.000000 }, - {3009,3009, 42, 0, 33, 33,0.000000 }, - { 369, 369, 50, 0, 100, 100,0.000000 }, - { 369, 369, 52, 0, 66, 66,0.000000 }, - { 369, 369, 54, 0, 93, 93,0.000000 }, - { 369, 369, 55, 0, 86, 86,0.000000 }, - { 369, 369, 57, 0, 100, 100,0.000000 }, - {3010,3010, 51, 0, 333, 333,0.000000 }, - { 144, 144, 61, 0, 40, 40,0.000000 }, - {3016,3016, 0, 0, 106, 106,0.000000 }, - {3016,3016, 63, 0, 86, 86,0.000000 }, - {3016,3016, 64, 0, 86, 86,0.000000 }, - {3017,3017, 40, 0, 60, 60,0.000000 }, - {3017,3017, 70, 0, 40, 40,0.000000 }, - {3018,3018, 0, 0, 40000, 6,0.000000 }, - {3019,3019, 0, 0, 40000, 0,0.000000 }, - {3020,3020, 0, 0, 40000, 6,0.000000 }, - {3021,3021, 0, 0, 40000, 6,0.000000 }, - {3022,3022, 38, 0, 46, 46,0.000000 }, - {2441,2441, 57, 0, 73, 73,0.000000 }, - {3023,3023, 63, 0, 33, 33,0.000000 }, - {3024,3024, 74, 0, 80, 80,0.000000 }, - {3025,3025, 74, 0, 206, 206,0.000000 }, - {3026,3026, 60, 0, 300, 300,0.000000 }, - {1593,1594, 35, 0, 646, 646,0.000000 }, - {1564,1565, 35, 0, 66, 66,0.000000 }, - { 248,3027, 0, 0, 40000, 33,0.000000 }, - {1445,3028, 0, 0, 1860, 1860,0.000000 }, - {1447,3029, 0, 0, 1626, 1626,0.000000 }, - {1452,3030, 0, 0, 1740, 1740,0.000000 }, - {1544,3031, 0, 0, 160, 160,0.000000 }, - {1546,3032, 0, 0, 1913, 1913,0.000000 }, - { 398, 399, 35, 0, 600, 600,0.000000 }, - {1550,3033, 35, 0, 20, 20,0.000000 }, - {1556,1557, 35, 0, 386, 386,0.000000 }, - {1558,1559, 35, 0, 346, 346,0.000000 }, - {1570,1571, 35, 0, 360, 360,0.000000 }, - {1608,1609, 35, 0, 460, 460,0.000000 }, - {1595,1596, 35, 0, 60, 60,0.000000 }, - { 159,1597, 35, 0, 60, 60,0.000000 }, - {1610,1611, 35, 0, 60, 60,0.000000 }, - { 397,1588, 35, 0, 100, 100,0.000000 }, - {1606,1607, 35, 0, 46, 46,0.000000 }, - { 145,1576, 35, 0, 6, 6,0.000000 }, - {1612,1613, 35, 0, 60, 60,0.000000 }, - {1577,1578, 35, 0, 53, 53,0.000000 }, - {1614,1615, 35, 0, 6, 6,0.000000 }, - {1550,1551, 35, 0, 20, 20,0.000000 }, - { 364, 365, 35, 0, 20, 20,0.000000 }, - { 129,1549, 35, 0, 93, 93,0.000000 }, - { 132,1552, 35, 0, 20, 20,0.000000 }, - {1553,1554, 35, 0, 33, 33,0.000000 }, - { 129,1548, 35, 0, 86, 86,0.000000 }, - { 134,1555, 35, 0, 133, 133,0.000000 }, - {1560,1561, 35, 0, 140, 140,0.000000 }, - {1562,1563, 35, 0, 40000, 0,0.000000 }, - {1572,1573, 35, 0, 66, 66,0.000000 }, - {1574,1575, 35, 0, 60, 60,0.000000 }, - {1581,1582, 35, 0, 20, 20,0.000000 }, - { 149,1583, 35, 0, 53, 53,0.000000 }, - {1584,1585, 35, 0, 206, 206,0.000000 }, - {1591,1592, 35, 0, 386, 386,0.000000 }, - {1579,1580, 35, 0, 53, 53,0.000000 }, - {1586,1587, 35, 0, 180, 180,0.000000 }, - {1589,1590, 35, 0, 20, 20,0.000000 }, - {1600,1601, 35, 0, 140, 140,0.000000 }, - {1602,1603, 35, 0, 220, 220,0.000000 }, - {1604,1605, 35, 0, 1293, 1293,0.000000 }, - {1598,1599, 35, 0, 233, 233,0.000000 }, - { 374, 375, 35, 0, 580, 580,0.000000 }, - {1566,1567, 35, 0, 1666, 0,0.000000 }, - {2306,2307, 35, 0, 140, 140,0.000000 }, - {3034, 339, 35, 0, 4293, 4293,0.000000 }, - {2305,1548, 35, 0, 80, 80,0.000000 }, - {1595,1595, 35, 0, 60, 60,0.000000 }, - {2303,2304, 35, 0, 20, 20,0.000000 }, - {1560,2308, 35, 0, 140, 140,0.000000 }, - {2309,2310, 35, 0, 40000, 0,0.000000 }, - {1568,1568, 35, 0, 20, 20,0.000000 }, - {2311,2312, 35, 0, 66, 66,0.000000 }, - {2313,2314, 35, 0, 66, 66,0.000000 }, - {2315,2315, 35, 0, 13, 13,0.000000 }, - {2316,2316, 35, 0, 53, 53,0.000000 }, - {1612,1612, 35, 0, 60, 60,0.000000 }, - {2317,2317, 35, 0, 153, 153,0.000000 }, - {2318,2318, 35, 0, 86, 86,0.000000 }, - {2319,2319, 35, 0, 46, 46,0.000000 }, - {2320,2320, 35, 0, 46, 46,0.000000 }, - {2321,2321, 35, 0, 20, 20,0.000000 }, - {2322,2322, 35, 0, 426, 426,0.000000 }, - {2323,2323, 35, 0, 826, 826,0.000000 }, - {2324, 392, 35, 0, 20, 20,0.000000 }, - {2324, 393, 35, 0, 346, 346,0.000000 }, - {2325,2326, 35, 0, 220, 220,0.000000 }, - {2327,2328, 35, 0, 180, 180,0.000000 }, - {2329,2330, 35, 0, 160, 160,0.000000 }, - {2331,2332, 35, 0, 573, 573,0.000000 }, - {3035,3036, 35, 0, 1026, 1026,0.000000 }, - {3037,3038, 35, 0, 400, 400,0.000000 }, - {1564,1564, 35, 0, 60, 60,0.000000 }, - {3039,3039, 0, 0, 2293, 2293,0.000000 }, - {3040,3040, 0, 0, 2006, 2006,0.000000 }, - {3041,3041, 0, 0, 1226, 1226,0.000000 }, - {3042,3042, 0, 0, 1026, 1026,0.000000 }, - {3043,3043, 0, 0, 760, 760,0.000000 }, - {3044,3044, 0, 0, 546, 546,0.000000 }, - {3045,3045, 0, 0, 613, 613,0.000000 }, - {3046,3046, 0, 0, 40000, 53,0.000000 }, - {3047,3047, 0, 0, 1013, 1013,0.000000 }, - {3048,3048, 0, 0, 40000, 606,0.000000 }, - {3049,3049, 0, 0, 3626, 3626,0.000000 }, - {3050,3050, 0, 0, 993, 993,0.000000 }, - {3051,3051, 0, 0, 266, 266,0.000000 }, - {3052,3052, 0, 0, 140, 140,0.000000 }, - {3053,3053, 0, 0, 2253, 2253,0.000000 }, - {3054,3054, 0, 0, 2513, 2513,0.000000 }, - {3055,3055, 0, 0, 40000, 0,0.000000 }, - {3056,3056, 0, 0, 40000, 0,0.000000 }, - {3057,3057, 0, 0, 2146, 2146,0.000000 }, - {3058,3058, 0, 0, 40000, 0,0.000000 }, - {3059,3059, 0, 0, 40000, 6,0.000000 }, - {3060,3060, 0, 0, 40000, 6,0.000000 }, - {3061,3061, 0, 0, 460, 460,0.000000 }, - {3062,3062, 0, 0, 1846, 1846,0.000000 }, - {3063,3063, 0, 0, 933, 933,0.000000 }, - {3064,3064, 0, 0, 206, 206,0.000000 }, - {3065,3065, 0, 0, 40000, 20,0.000000 }, - {3066,3066, 0, 0, 80, 80,0.000000 }, - {3067,3067, 0, 0, 1973, 1973,0.000000 }, - {3068,3068, 0, 0, 40000, 60,0.000000 }, - {3069,3069, 0, 0, 1120, 1120,0.000000 }, - {3070,3070, 0, 0, 420, 420,0.000000 }, - {3071,3071, 0, 0, 1120, 1120,0.000000 }, - {3072,3072, 0, 0, 806, 806,0.000000 }, - {3073,3073, 0, 0, 1186, 1186,0.000000 }, - {3074,3074, 0, 0, 1900, 1900,0.000000 }, - {3075,3075, 0, 0, 40000, 0,0.000000 }, - {3076,3076, 0, 0, 1046, 1046,0.000000 }, - {3077,3077, 0, 0, 600, 600,0.000000 }, - {3078,3078, 0, 0, 146, 13,0.000000 }, - {3079,3079, 0, 0, 786, 786,0.000000 }, - {3080,3080, 0, 0, 40000, 26,0.000000 }, - {3081,3081, 0, 0, 146, 13,0.000000 }, - {3082,3082, 0, 0, 40000, 46,0.000000 }, - {3083,3083, 0, 0, 100, 100,0.000000 }, - {3084,3084, 0, 0, 1580, 1580,0.000000 }, - {3085,3085, 0, 0, 280, 280,0.000000 }, - {3086,3086, 0, 0, 40000, 80,0.000000 }, - {3087,3087, 0, 0, 40000, 73,0.000000 }, - {3088,3088, 0, 0, 40000, 66,0.000000 }, - {3089,3089, 0, 0, 40000, 73,0.000000 }, - {3090,3090, 0, 0, 40000, 0,0.000000 }, - {3091,3091, 0, 0, 40000, 6,0.000000 }, - {3092,3092, 0, 0, 40000, 6,0.000000 }, - {3093,3093, 0, 0, 246, 246,0.000000 }, - {3094,3094, 0, 0, 40000, 73,0.000000 }, - {3095,3095, 0, 0, 273, 126,0.000000 }, - {3096,3096, 0, 0, 40000, 33,0.000000 }, - {3097,3097, 0, 0, 40000, 6,0.000000 }, - {3098,3098, 0, 0, 40000, 73,0.000000 }, - {3099,3099, 0, 0, 1233, 53,0.000000 }, - {3100,3100, 0, 0, 40000, 66,0.000000 }, - {3101,3101, 0, 0, 40000, 0,0.000000 }, - {3102,3102, 0, 0, 40000, 0,0.000000 }, - {3103,3103, 0, 0, 40000, 6,0.000000 }, - {3104,3104, 0, 0, 40000, 0,0.000000 }, - {3105,3105, 0, 0, 40000, 6,0.000000 }, - {3106,3106, 0, 0, 40000, 0,0.000000 }, - {3107,3107, 0, 0, 40000, 0,0.000000 }, - {3108,3108, 0, 0, 40000, 6,0.000000 }, - {3109,3109, 0, 0, 40000, 6,0.000000 }, - {3110,3110, 0, 0, 40000, 6,0.000000 }, - {3111,3111, 0, 0, 40000, 20,0.000000 }, - {3112,3112, 0, 0, 2240, 2240,0.000000 }, - {3113,3113, 0, 0, 100, 6,0.000000 }, - {3114,3114, 0, 0, 4466, 4466,0.000000 }, - {3115,3115, 0, 0, 40000, 20,0.000000 }, - {3116,3116, 0, 0, 40000, 13,0.000000 }, - {3117,3117, 0, 0, 40000, 53,0.000000 }, - {3118,3118, 0, 0, 40000, 300,0.000000 }, - {3119,3119, 0, 0, 6906, 6906,0.000000 }, - {3120,3120, 0, 0, 40000, 33,0.000000 }, - {3121,3121, 0, 0, 40000, 6,0.000000 }, - {3122,3122, 0, 0, 1953, 1953,0.000000 }, - {3123,3123, 0, 0, 973, 973,0.000000 }, - {3124,3124, 0, 0, 2240, 6,0.000000 }, - {3125,3125, 0, 0, 1986, 1986,0.000000 }, - {3126,3126, 0, 0, 1613, 1613,0.000000 }, - {3127,3127, 0, 0, 353, 353,0.000000 }, - {3128,3128, 0, 0, 66, 66,0.000000 }, - {3129,3129, 0, 0, 5586, 5586,0.000000 }, - {3130,3130, 0, 0, 173, 173,0.000000 }, - {3131,3131, 35, 0, 120, 120,0.000000 }, - {3132,3132, 35, 0, 6, 6,0.000000 }, - {3133,3133, 35, 0, 40000, 46,0.000000 }, - {3134,3134, 35, 0, 40000, 46,0.000000 }, - {3135,3135, 35, 0, 100, 100,0.000000 }, - {3061,3061, 35, 0, 140, 140,0.000000 }, - {3136,3136, 35, 0, 20, 20,0.000000 }, - { 739, 739, 35, 0, 40, 40,0.000000 }, - {3137,3137, 35, 0, 186, 186,0.000000 }, - {3138,3138, 35, 0, 160, 160,0.000000 }, - {3139,3139, 35, 0, 93, 93,0.000000 }, - {3140,3140, 35, 0, 80, 80,0.000000 }, - {3141,3141, 35, 0, 133, 133,0.000000 }, - {3142,3142, 35, 0, 66, 66,0.000000 }, - {3143,3143, 35, 0, 133, 133,0.000000 }, - {3144,3144, 35, 0, 666, 666,0.000000 }, - {3145,3145, 35, 0, 93, 93,0.000000 }, - {3146,3146, 35, 0, 1433, 1433,0.000000 }, - {3147,3147, 35, 0, 393, 393,0.000000 }, - {3148,3148, 35, 0, 93, 93,0.000000 }, - {3149,3149, 35, 0, 1480, 1480,0.000000 }, - {3150,3150, 0, 0, 1126, 1126,0.000000 }, - {3151,3151, 0, 0, 1766, 1766,0.000000 }, - {3152,3152, 0, 0, 620, 620,0.000000 }, - {3153,3153, 0, 0, 460, 460,0.000000 }, - {3154,3154, 0, 0, 1173, 1173,0.000000 }, - {3155,3155, 0, 0, 626, 626,0.000000 }, - {3156,3156, 0, 0, 1740, 1740,0.000000 }, - {3157,3157, 0, 0, 280, 280,0.000000 }, - {3158,3158, 0, 0, 46, 46,0.000000 }, - {3159,3159, 0, 0, 280, 280,0.000000 }, - {3160,3160, 0, 0, 1153, 1153,0.000000 }, - {3161,3161, 0, 0, 40000, 0,0.000000 }, - {3162,3162, 0, 0, 40000, 6,0.000000 }, - {3163,3163, 0, 0, 40000, 46,0.000000 }, - {3164,3164, 0, 0, 40000, 0,0.000000 }, - {3165,3165, 0, 0, 40000, 6,0.000000 }, - {3166,3166, 0, 0, 2280, 2280,0.000000 }, - {3167,3167, 0, 0, 40000, 0,0.000000 }, - {3168,3168, 0, 0, 486, 486,0.000000 }, - {3169,3169, 0, 0, 600, 600,0.000000 }, - {3170,3170, 0, 0, 466, 466,0.000000 }, - {3171,3171, 0, 0, 593, 593,0.000000 }, - {3172,3172, 0, 0, 1153, 1153,0.000000 }, - {3173,3173, 0, 0, 280, 280,0.000000 }, - {3174,3174, 0, 0, 586, 586,0.000000 }, - {3175,3175, 0, 0, 206, 13,0.000000 }, - {3176,3176, 0, 0, 186, 60,0.000000 }, - {3177,3177, 0, 0, 2366, 2366,0.000000 }, - {3178,3178, 0, 0, 1700, 1700,0.000000 }, - {3179,3179, 0, 0, 46, 46,0.000000 }, - {3180,3180, 0, 0, 886, 886,0.000000 }, - {3181,3181, 0, 0, 186, 186,0.000000 }, - {3182,3182, 0, 0, 40000, 186,0.000000 }, - {3183,3183, 0, 0, 560, 560,0.000000 }, - {3184,3184, 0, 0, 1466, 1466,0.000000 }, - {3185,3185, 0, 0, 1553, 1553,0.000000 }, - {3186,3186, 0, 0, 380, 380,0.000000 }, - {3187,3187, 0, 0, 146, 146,0.000000 }, - {3188,3188, 0, 0, 146, 146,0.000000 }, - {3189,3189, 0, 0, 4726, 4726,0.000000 }, - {3190,3190, 0, 0, 40000, 6,0.000000 }, - {3191,3191, 0, 0, 1766, 1766,0.000000 }, - {3192,3192, 0, 0, 40000, 0,0.000000 }, - {3193,3193, 0, 0, 806, 806,0.000000 }, - {3194,3194, 0, 0, 1133, 1133,0.000000 }, - {3195,3195, 0, 0, 40000, 6,0.000000 }, - {3196,3196, 0, 0, 40000, 0,0.000000 }, - {3197,3197, 0, 0, 40000, 6,0.000000 }, - {3198,3198, 0, 0, 40000, 20,0.000000 }, - {3199,3199, 0, 0, 40000, 6,0.000000 }, - {3200,3200, 0, 0, 213, 213,0.000000 }, - {3201,3201, 0, 0, 40000, 106,0.000000 }, - {3202,3202, 0, 0, 1113, 1113,0.000000 }, - {3203,3203, 0, 0, 1953, 1953,0.000000 }, - {3204,3204, 0, 0, 40000, 0,0.000000 }, - {3205,3205, 0, 0, 40000, 0,0.000000 }, - {3206,3206, 0, 0, 340, 340,0.000000 }, - {3207,3207, 0, 0, 40000, 6,0.000000 }, - {3208,3208, 0, 0, 1126, 1126,0.000000 }, - {3209,3209, 0, 0, 300, 300,0.000000 }, - {3210,3210, 0, 0, 40000, 46,0.000000 }, - {3211,3211, 0, 0, 40000, 113,0.000000 }, - {3212,3212, 0, 0, 1126, 1126,0.000000 }, - {3213,3213, 0, 0, 2853, 2853,0.000000 }, - {3214,3214, 0, 0, 40000, 0,0.000000 }, - {3215,3215, 0, 0, 1286, 0,0.000000 }, - {3216,3216, 0, 0, 40000, 233,0.000000 }, - {3217,3217, 0, 0, 40000, 1640,0.000000 }, - {3218,3218, 0, 0, 40000, 240,0.000000 }, - {3219,3219, 0, 0, 1766, 1766,0.000000 }, - {3220,3220, 0, 0, 40000, 1493,0.000000 }, - {3221,3221, 0, 0, 40000, 2120,0.000000 }, - {3222,3222, 0, 0, 1226, 1226,0.000000 }, - {3223,3223, 0, 0, 306, 306,0.000000 }, - {3224,3224, 0, 0, 40000, 6,0.000000 }, - {3225,3225, 0, 0, 666, 13,0.000000 }, - {3226,3226, 0, 0, 153, 153,0.000000 }, - {3227,3227, 0, 0, 626, 626,0.000000 }, - {3228,3228, 0, 0, 140, 140,0.000000 }, - {3229,3229, 0, 0, 233, 233,0.000000 }, - { 499, 499, 0, 0, 40, 40,0.000000 }, - {3230,3230, 0, 0, 46, 46,0.000000 }, - {3231,3231, 0, 0, 146, 146,0.000000 }, - {3232,3232, 0, 0, 206, 206,0.000000 }, - {3233,3233, 0, 0, 5686, 5686,0.000000 }, - {3234,3234, 0, 0, 326, 326,0.000000 }, - { 403, 403, 0, 0, 40000, 0,0.000000 }, - {3235,3235, 0, 0, 1913, 1913,0.000000 }, - {3236,3236, 0, 0, 2080, 2080,0.000000 }, - {3237,3237, 0, 0, 2026, 2026,0.000000 }, - {3238,3238, 0, 0, 1166, 1166,0.000000 }, - {3239,3239, 0, 0, 600, 600,0.000000 }, - {3240,3240, 0, 0, 1213, 1213,0.000000 }, - {3241,3241, 0, 0, 40000, 0,0.000000 }, - {3242,3242, 0, 0, 40000, 0,0.000000 }, - {3243,3243, 0, 0, 40000, 0,0.000000 }, - {3244,3244, 0, 0, 40000, 0,0.000000 }, - {3245,3245, 0, 0, 40000, 146,0.000000 }, - {3246,3246, 0, 0, 40000, 146,0.000000 }, - {3247,3247, 0, 0, 40000, 146,0.000000 }, - {3248,3248, 0, 0, 40000, 153,0.000000 }, - {3249,3249, 0, 0, 873, 873,0.000000 }, - {3250,3250, 0, 0, 553, 553,0.000000 }, - {3251,3251, 0, 0, 873, 873,0.000000 }, - {3252,3252, 0, 0, 606, 606,0.000000 }, - {3253,3253, 0, 0, 606, 606,0.000000 }, - {3254,3254, 0, 0, 600, 600,0.000000 }, - {3255,3255, 0, 0, 1013, 1013,0.000000 }, - {3256,3256, 0, 0, 626, 626,0.000000 }, - {3257,3257, 0, 0, 40000, 0,0.000000 }, - {3258,3258, 0, 0, 40000, 0,0.000000 }, - {3259,3259, 0, 0, 40000, 66,0.000000 }, - {3260,3260, 0, 0, 40000, 66,0.000000 }, - {3261,3261, 0, 0, 40000, 20,0.000000 }, - {3262,3262, 0, 0, 1120, 1120,0.000000 }, - {3263,3263, 0, 0, 1206, 1206,0.000000 }, - {3264,3264, 0, 0, 940, 940,0.000000 }, - {3265,3265, 0, 0, 3626, 3626,0.000000 }, - {3266,3266, 0, 0, 40000, 320,0.000000 }, - {3267,3267, 0, 0, 40000, 6,0.000000 }, - {3268,3268, 0, 0, 3926, 3926,0.000000 }, - {3269,3269, 0, 0, 40000, 446,0.000000 }, - {3270,3270, 0, 0, 40000, 180,0.000000 }, - {3271,3271, 0, 0, 3426, 3426,0.000000 }, - {3272,3272, 0, 0, 2253, 2253,0.000000 }, - {3273,3273, 0, 0, 40000, 2133,0.000000 }, - {3274,3274, 0, 0, 2566, 2566,0.000000 }, - {3275,3275, 0, 0, 166, 26,0.000000 }, - {3276,3276, 0, 0, 40000, 346,0.000000 }, - {3277,3277, 0, 0, 40000, 66,0.000000 }, - {3278,3278, 0, 0, 40000, 213,0.000000 }, - {3279,3279, 0, 0, 2273, 2273,0.000000 }, - {3280,3280, 0, 0, 40000, 40,0.000000 }, - {3281,3281, 0, 0, 40000, 906,0.000000 }, - {3282,3282, 0, 0, 40000, 213,0.000000 }, - {3283,3283, 0, 0, 40000, 186,0.000000 }, - {3284,3284, 0, 0, 60, 60,0.000000 }, - {3285,3285, 0, 0, 146, 146,0.000000 }, - {3286,3286, 0, 0, 146, 13,0.000000 }, - {3287,3287, 0, 0, 786, 786,0.000000 }, - {3288,3288, 0, 0, 40000, 26,0.000000 }, - {3289,3289, 0, 0, 1580, 1580,0.000000 }, - {3290,3290, 0, 0, 653, 653,0.000000 }, - {3291,3291, 0, 0, 2400, 2400,0.000000 }, - {3292,3292, 0, 0, 1926, 1926,0.000000 }, - {3293,3293, 0, 0, 2593, 2593,0.000000 }, - {3294,3294, 0, 0, 2360, 2360,0.000000 }, - {3295,3295, 0, 0, 4933, 4933,0.000000 }, - {3296,3296, 0, 0, 593, 593,0.000000 }, - {3297,3297, 0, 0, 253, 253,0.000000 }, - {3298,3298, 0, 0, 306, 306,0.000000 }, - {3299,3299, 0, 0, 613, 613,0.000000 }, - {3300,3300, 0, 0, 1900, 1900,0.000000 }, - {3301,3301, 0, 0, 1213, 1213,0.000000 }, - {3302,3302, 0, 0, 273, 273,0.000000 }, - {3303,3303, 0, 0, 566, 566,0.000000 }, - {3304,3304, 0, 0, 40000, 6,0.000000 }, - {3305,3305, 0, 0, 40000, 6,0.000000 }, - {3306,3306, 0, 0, 40000, 6,0.000000 }, - {3307,3307, 0, 0, 40000, 6,0.000000 }, - {3308,3308, 0, 0, 40000, 6,0.000000 }, - {3309,3309, 0, 0, 40000, 0,0.000000 }, - {3310,3310, 0, 0, 40000, 0,0.000000 }, - {3311,3311, 0, 0, 40000, 0,0.000000 }, - {3312,3312, 0, 0, 40000, 6,0.000000 }, - {3313,3313, 0, 0, 40000, 53,0.000000 }, - {3314,3314, 0, 0, 40000, 73,0.000000 }, - {3315,3315, 0, 0, 40000, 0,0.000000 }, - {3316,3316, 0, 0, 40000, 0,0.000000 }, - {3317,3317, 0, 0, 40000, 0,0.000000 }, - {3318,3318, 0, 0, 40000, 80,0.000000 }, - {3319,3319, 0, 0, 40, 60,0.000000 }, - {3320,3320, 0, 0, 1320, 1320,0.000000 }, - {3321,3321, 0, 0, 40000, 126,0.000000 }, - {3322,3322, 0, 0, 273, 126,0.000000 }, - {3323,3323, 0, 0, 40000, 126,0.000000 }, - {3324,3324, 0, 0, 40000, 33,0.000000 }, - {3325,3325, 0, 0, 40000, 73,0.000000 }, - {3326,3326, 0, 0, 40, 40,0.000000 }, - {3327,3327, 0, 0, 40000, 233,0.000000 }, - {3328,3328, 0, 0, 40000, 233,0.000000 }, - {3329,3329, 0, 0, 593, 593,0.000000 }, - {3330,3330, 0, 0, 40000, 213,0.000000 }, - {3331,3331, 0, 0, 40000, 606,0.000000 }, - {3332,3332, 0, 0, 2253, 2253,0.000000 }, - {3333,3333, 0, 0, 140, 140,0.000000 }, - {3334,3334, 0, 0, 40000, 926,0.000000 }, - {3335,3335, 0, 0, 40000, 33,0.000000 }, - {3336,3336, 0, 0, 40000, 1120,0.000000 }, - {3337,3337, 0, 0, 160, 160,0.000000 }, - {3338,3338, 0, 0, 40000, 6,0.000000 }, - {3339,3339, 0, 0, 40000, 1093,0.000000 }, - {3340,3340, 0, 0, 160, 160,0.000000 }, - {3341,3341, 0, 0, 1206, 1206,0.000000 }, - {3342,3342, 0, 0, 146, 146,0.000000 }, - {3343,3343, 0, 0, 146, 146,0.000000 }, - {3344,3344, 0, 0, 140, 140,0.000000 }, - {3345,3345, 0, 0, 140, 140,0.000000 }, - {3346,3346, 0, 0, 140, 140,0.000000 }, - {3347,3347, 0, 0, 80, 80,0.000000 }, - {3348,3348, 0, 0, 40000, 33,0.000000 }, - {3349,3349, 0, 0, 1186, 1186,0.000000 }, - {3350,3350, 0, 0, 40000, 1413,0.000000 }, - {3351,3351, 0, 0, 1226, 1226,0.000000 }, - {3352,3352, 0, 0, 40, 40,0.000000 }, - {3353,3353, 0, 0, 60, 60,0.000000 }, - {3354,3354, 0, 0, 100, 100,0.000000 }, - {3355,3355, 0, 0, 246, 246,0.000000 }, - {3356,3356, 0, 0, 1140, 1140,0.000000 }, - { 142, 142, 20, 0, 20, 20,0.000000 }, - {3357,1451, 0, 0, 613, 613,0.000000 }, - {3358,3359, 0, 0, 1740, 1740,0.000000 }, - {3360,1455, 0, 0, 280, 280,0.000000 }, - {3361,1463, 0, 0, 40000, 133,0.000000 }, - { 225,3362, 0, 0, 2026, 2026,0.000000 }, - {3363,1545, 0, 0, 153, 153,0.000000 }, - {3364,1547, 0, 0, 40000, 60,0.000000 }, - {3365,3366, 39, 0, 13, 13,0.000000 }, - {3367, 368, 58, 0, 46, 46,0.000000 }, - {3368,1551, 48, 0, 93, 93,0.000000 }, - {3368,3033, 49, 0, 73, 73,0.000000 }, - {3368,3033, 51, 0, 153, 153,0.000000 }, - {3368,3033, 54, 0, 140, 140,0.000000 }, - {3368,3033, 57, 0, 126, 126,0.000000 }, - {3368,3033, 60, 0, 133, 133,0.000000 }, - {3369,3370, 70, 0, 893, 893,0.000000 }, - {1564,1565, 80, 0, 66, 66,0.000000 }, - {3371,1571, 44, 0, 520, 520,0.000000 }, - {3372,3372, 0, 0, 1486, 1486,0.000000 }, - {3373,3373, 0, 0, 1806, 1806,0.000000 }, - {3374,3374, 0, 0, 633, 633,0.000000 }, - {3375,3375, 0, 0, 1273, 1273,0.000000 }, - {3376,3376, 0, 0, 1553, 1553,0.000000 }, - {3377,3377, 0, 0, 1206, 1206,0.000000 }, - {3378,3378, 0, 0, 313, 313,0.000000 }, - {3379,3379, 0, 0, 1486, 1486,0.000000 }, - {3380,3380, 0, 0, 626, 626,0.000000 }, - {3381,3381, 0, 0, 1846, 1846,0.000000 }, - {3382,3382, 0, 0, 300, 300,0.000000 }, - {3383,3383, 0, 0, 1740, 1740,0.000000 }, - {3384,3384, 0, 0, 513, 513,0.000000 }, - {3385,3385, 0, 0, 46, 46,0.000000 }, - {3386,3386, 0, 0, 1226, 1226,0.000000 }, - {3387,3387, 0, 0, 333, 333,0.000000 }, - {3388,3388, 0, 0, 40000, 300,0.000000 }, - {3389,3389, 0, 0, 40000, 533,0.000000 }, - {3390,3390, 0, 0, 40000, 126,0.000000 }, - {3391,3391, 0, 0, 40000, 0,0.000000 }, - {3392,3392, 0, 0, 40000, 33,0.000000 }, - {3393,3393, 0, 0, 40000, 6,0.000000 }, - {3394,3394, 0, 0, 40000, 6,0.000000 }, - {3395,3395, 0, 0, 3880, 6,0.000000 }, - {3396,3396, 0, 0, 1066, 1066,0.000000 }, - {3397,3397, 0, 0, 4086, 4086,0.000000 }, - {3398,3398, 0, 0, 866, 866,0.000000 }, - {3399,3399, 0, 0, 466, 466,0.000000 }, - {3400,3400, 0, 0, 420, 420,0.000000 }, - {3401,3401, 0, 0, 40000, 73,0.000000 }, - {3402,3402, 0, 0, 40000, 20,0.000000 }, - {3403,3403, 0, 0, 40000, 26,0.000000 }, - {3404,3404, 0, 0, 4266, 4266,0.000000 }, - {3405,3405, 0, 0, 40000, 0,0.000000 }, - {3406,3406, 0, 0, 253, 253,0.000000 }, - {3407,3407, 0, 0, 380, 380,0.000000 }, - {3408,3408, 0, 0, 573, 573,0.000000 }, - {3409,3409, 0, 0, 280, 280,0.000000 }, - {3410,3410, 0, 0, 40000, 6,0.000000 }, - {3411,3411, 0, 0, 1933, 1933,0.000000 }, - {3412,3412, 0, 0, 40000, 140,0.000000 }, - {3413,3413, 0, 0, 40000, 140,0.000000 }, - {3414,3414, 0, 0, 40000, 40,0.000000 }, - {3415,3415, 0, 0, 353, 353,0.000000 }, - {3416,3416, 0, 0, 40000, 166,0.000000 }, - {3417,3417, 0, 0, 273, 273,0.000000 }, - {3418,3418, 0, 0, 126, 126,0.000000 }, - {3419,3419, 0, 0, 146, 146,0.000000 }, - {3420,3420, 0, 0, 40000, 213,0.000000 }, - {3421,3421, 0, 0, 40000, 173,0.000000 }, - {3422,3422, 0, 0, 40000, 206,0.000000 }, - {3423,3423, 0, 0, 40000, 213,0.000000 }, - {3424,3424, 0, 0, 40000, 153,0.000000 }, - {3425,3425, 0, 0, 40000, 106,0.000000 }, - {3426,3426, 0, 0, 40000, 6,0.000000 }, - {3427,3427, 0, 0, 233, 233,0.000000 }, - {3428,3428, 0, 0, 40000, 6,0.000000 }, - {3429,3429, 0, 0, 11193, 13,0.000000 }, - {3430,3430, 0, 0, 40000, 126,0.000000 }, - {3431,3431, 0, 0, 40000, 13,0.000000 }, - {3432,3432, 0, 0, 40000, 6,0.000000 }, - {3433,3433, 0, 0, 40000, 0,0.000000 }, - {3434,3434, 0, 0, 40000, 0,0.000000 }, - {3435,3435, 0, 0, 40000, 0,0.000000 }, - {3436,3436, 0, 0, 40000, 0,0.000000 }, - {3437,3437, 0, 0, 40000, 0,0.000000 }, - {3438,3438, 0, 0, 40000, 0,0.000000 }, - {3439,3439, 0, 0, 6013, 6013,0.000000 }, - {3440,3440, 0, 0, 40000, 0,0.000000 }, - {3441,3441, 0, 0, 40000, 0,0.000000 }, - {3442,3442, 0, 0, 293, 293,0.000000 }, - {3443,3443, 0, 0, 40000, 6,0.000000 }, - {3444,3444, 0, 0, 40000, 20,0.000000 }, - {3445,3445, 0, 0, 40000, 0,0.000000 }, - {3446,3446, 0, 0, 40000, 0,0.000000 }, - {3447,3447, 0, 0, 40000, 0,0.000000 }, - {3448,3448, 0, 0, 40000, 0,0.000000 }, - {3449,3449, 0, 0, 40000, 20,0.000000 }, - {3450,3450, 0, 0, 40000, 153,0.000000 }, - {3451,3451, 0, 0, 440, 440,0.000000 }, - {3452,3452, 0, 0, 3253, 3253,0.000000 }, - {3453,3453, 0, 0, 3946, 3946,0.000000 }, - {3454,3454, 0, 0, 140, 140,0.000000 }, - {3455,3455, 0, 0, 40000, 20,0.000000 }, - {3456,3456, 0, 0, 40000, 33,0.000000 }, - {3457,3457, 0, 0, 40000, 20,0.000000 }, - {3458,3458, 0, 0, 40000, 26,0.000000 }, - {3459,3459, 0, 0, 40000, 20,0.000000 }, - {3460,3460, 0, 0, 786, 786,0.000000 }, - {3461,3461, 0, 0, 2560, 2560,0.000000 }, - {3462,3462, 0, 0, 40000, 26,0.000000 }, - {3463,3463, 0, 0, 40000, 580,0.000000 }, - {3464,3464, 0, 0, 40000, 2393,0.000000 }, - {3465,3465, 0, 0, 40000, 53,0.000000 }, - {3466,3466, 0, 0, 40000, 33,0.000000 }, - {3467,3467, 0, 0, 40000, 193,0.000000 }, - {3468,3468, 0, 0, 40000, 280,0.000000 }, - {3469,3469, 0, 0, 40000, 86,0.000000 }, - {3470,3470, 0, 0, 40000, 820,0.000000 }, - {3471,3471, 0, 0, 40000, 286,0.000000 }, - {3472,3472, 0, 0, 40000, 1100,0.000000 }, - {3473,3473, 0, 0, 40000, 1073,0.000000 }, - {3474,3474, 0, 0, 40000, 1173,0.000000 }, - {3475,3475, 0, 0, 340, 340,0.000000 }, - {3476,3476, 0, 0, 4846, 4846,0.000000 }, - {3477,3477, 0, 0, 40000, 0,0.000000 }, - {3478,3478, 0, 0, 4846, 4846,0.000000 }, - {3479,3479, 0, 0, 606, 606,0.000000 }, - {3480,3480, 0, 0, 106, 106,0.000000 }, - {3481,3481, 0, 0, 40000, 0,0.000000 }, - {3482,3482, 0, 0, 40000, 73,0.000000 }, - {3483,3483, 0, 0, 40000, 0,0.000000 }, - {3484,3484, 0, 0, 586, 586,0.000000 }, - {3485,3485, 0, 0, 73, 73,0.000000 }, - {3486,3486, 0, 0, 460, 460,0.000000 }, - {3487,3487, 0, 0, 40, 40,0.000000 }, - {3488,3488, 0, 0, 526, 526,0.000000 }, - {3489,3489, 0, 0, 540, 540,0.000000 }, - {3490,3490, 0, 0, 253, 253,0.000000 }, - {3491,3491, 0, 0, 2280, 2280,0.000000 }, - {3492,3492, 0, 0, 73, 73,0.000000 }, - {3493,3493, 0, 0, 40000, 73,0.000000 }, - {3494,3494, 0, 0, 40000, 2220,0.000000 }, - {3495,3495, 0, 0, 146, 146,0.000000 }, - {3496,3496, 0, 0, 40000, 13,0.000000 }, - {3497,3497, 0, 0, 380, 13,0.000000 }, - {3498,3498, 0, 0, 40000, 2220,0.000000 }, - {3499,3499, 0, 0, 40000, 146,0.000000 }, - {3500,3500, 0, 0, 1513, 13,0.000000 }, - { 739, 739, 46, 0, 53, 53,0.000000 }, - {3501,3501, 47, 0, 106, 106,0.000000 }, - {3502,3502, 64, 0, 26, 26,0.000000 }, - {3503,3503, 40, 0, 106, 106,0.000000 }, - {3504,3504, 48, 0, 13, 13,0.000000 }, - {3505,3505, 48, 0, 80, 80,0.000000 }, - {3506,3506, 46, 0, 86, 86,0.000000 }, - {3507,3507,111, 0, 33, 33,0.000000 }, - {3508,3508, 49, 0, 140, 140,0.000000 }, - {3509,3509, 56, 0, 33, 33,0.000000 }, - {3510,3510, 52, 0, 140, 140,0.000000 }, - {3511,3511, 96, 0, 440, 440,0.000000 }, - {3510,3510, 54, 0, 140, 140,0.000000 }, - {3512,3512, 57, 0, 260, 260,0.000000 }, - {3513,3513, 82, 0, 486, 486,0.000000 }, - {3510,3510, 60, 0, 153, 153,0.000000 }, - {3514,3514, 60, 0, 606, 606,0.000000 }, - {3515,3515, 92, 0, 60, 60,0.000000 }, - {3516,3516, 60, 0, 46, 46,0.000000 }, - {3517,3517, 58, 0, 40, 40,0.000000 }, - {3518,3518, 22, 0, 53, 53,0.000000 }, - {3519,3519, 60, 0, 613, 613,0.000000 }, - {3520,3520, 72, 0, 80, 80,0.000000 }, - {3521,3521, 77, 0, 80, 80,0.000000 }, - {3522,3522, 70, 0, 73, 73,0.000000 }, - {3523,3523, 75, 0, 60, 60,0.000000 }, - {3524,3524, 69, 0, 140, 140,0.000000 }, - {3525,3525, 59, 0, 113, 113,0.000000 }, - {3526,3526, 48, 0, 153, 153,0.000000 }, - {3527,3527, 89, 0, 133, 133,0.000000 }, - {3528,3528, 84, 0, 260, 260,0.000000 }, - {3529,3529, 33, 0, 93, 93,0.000000 }, - {3530,3530, 55, 0, 86, 86,0.000000 }, - {3531,3531, 58, 0, 186, 186,0.000000 }, - {3532,3532, 52, 0, 166, 166,0.000000 }, - {3533,3533, 57, 0, 46, 46,0.000000 }, - {3534,3534, 57, 0, 73, 73,0.000000 }, - {3535,3535, 85, 0, 60, 60,0.000000 }, - {3536,3536, 68, 0, 40, 40,0.000000 }, - {3536,3536, 61, 0, 60, 60,0.000000 }, - {3537,3537, 64, 0, 93, 93,0.000000 }, - {3538,3538, 44, 0, 386, 386,0.000000 }, - {3539,3539,100, 0, 80, 80,0.000000 }, - {3540,3540,100, 0, 306, 306,0.000000 }, - {3541,3541, 0, 0, 1400, 1400,0.000000 }, - {3542,3542, 0, 0, 253, 253,0.000000 }, - {3543,3543, 0, 0, 460, 460,0.000000 }, - {3544,3544, 0, 0, 1226, 1226,0.000000 }, - {3545,3545, 0, 0, 886, 886,0.000000 }, - {3546,3546, 0, 0, 40, 40,0.000000 }, - {3547,3547, 0, 0, 2406, 2406,0.000000 }, - {3548,3548, 0, 0, 1180, 1180,0.000000 }, - {3549,3549, 0, 0, 40000, 0,0.000000 }, - {3550,3550, 0, 0, 40000, 0,0.000000 }, - {3551,3551, 0, 0, 40000, 33,0.000000 }, - {3552,3552, 0, 0, 40000, 0,0.000000 }, - {3553,3553, 0, 0, 40000, 6,0.000000 }, - {3554,3554, 0, 0, 1553, 1553,0.000000 }, - {3555,3555, 0, 0, 40000, 0,0.000000 }, - {3556,3556, 0, 0, 573, 573,0.000000 }, - {3557,3557, 0, 0, 526, 526,0.000000 }, - {3558,3558, 0, 0, 940, 940,0.000000 }, - {3559,3559, 0, 0, 606, 606,0.000000 }, - {3560,3560, 0, 0, 40000, 6,0.000000 }, - {3561,3561, 0, 0, 40000, 0,0.000000 }, - {3562,3562, 0, 0, 1120, 1120,0.000000 }, - {3563,3563, 0, 0, 700, 700,0.000000 }, - {3564,3564, 0, 0, 66, 66,0.000000 }, - {3565,3565, 0, 0, 620, 620,0.000000 }, - {3566,3566, 0, 0, 286, 286,0.000000 }, - {3567,3567, 0, 0, 40000, 73,0.000000 }, - {3568,3568, 0, 0, 80, 80,0.000000 }, - {3569,3569, 0, 0, 186, 186,0.000000 }, - {3570,3570, 0, 0, 1506, 1506,0.000000 }, - {3571,3571, 0, 0, 40000, 0,0.000000 }, - {3572,3572, 0, 0, 40000, 186,0.000000 }, - {3573,3573, 0, 0, 126, 126,0.000000 }, - {3574,3574, 0, 0, 40000, 106,0.000000 }, - {3575,3575, 0, 0, 166, 166,0.000000 }, - {3576,3576, 0, 0, 80, 80,0.000000 }, - {3577,3577, 0, 0, 453, 13,0.000000 }, - {3578,3578, 0, 0, 40000, 0,0.000000 }, - {3579,3579, 0, 0, 40000, 6,0.000000 }, - {3580,3580, 0, 0, 2020, 2020,0.000000 }, - {3581,3581, 0, 0, 1646, 1646,0.000000 }, - {3582,3582, 0, 0, 166, 166,0.000000 }, - {3583,3583, 0, 0, 40000, 0,0.000000 }, - {3584,3584, 0, 0, 146, 146,0.000000 }, - {3585,3585, 0, 0, 340, 340,0.000000 }, - {3586,3586, 0, 0, 40000, 0,0.000000 }, - {3587,3587, 0, 0, 100, 13,0.000000 }, - {3588,3588, 0, 0, 5013, 5013,0.000000 }, - {3589,3589, 0, 0, 40000, 6,0.000000 }, - {3590,3590, 0, 0, 1766, 1766,0.000000 }, - {3591,3591, 0, 0, 4186, 4186,0.000000 }, - {3592,3592, 0, 0, 700, 700,0.000000 }, - {3593,3593, 0, 0, 940, 940,0.000000 }, - {3594,3594, 0, 0, 246, 246,0.000000 }, - {3595,3595, 0, 0, 40000, 6,0.000000 }, - {3596,3596, 0, 0, 40000, 6,0.000000 }, - {3597,3597, 0, 0, 40000, 6,0.000000 }, - {3598,3598, 0, 0, 40000, 0,0.000000 }, - {3599,3599, 0, 0, 40000, 306,0.000000 }, - {3600,3600, 0, 0, 40000, 53,0.000000 }, - {3601,3601, 0, 0, 40000, 6,0.000000 }, - {3602,3602, 0, 0, 40000, 233,0.000000 }, - {3603,3603, 0, 0, 120, 120,0.000000 }, - {3604,3604, 0, 0, 40000, 6,0.000000 }, - {3605,3605, 0, 0, 40000, 153,0.000000 }, - {3606,3606, 0, 0, 1086, 1086,0.000000 }, - {3607,3607, 0, 0, 1900, 1900,0.000000 }, - {3608,3608, 0, 0, 40000, 0,0.000000 }, - {3609,3609, 0, 0, 40000, 13,0.000000 }, - {3610,3610, 0, 0, 253, 253,0.000000 }, - {3611,3611, 0, 0, 40000, 6,0.000000 }, - {3612,3612, 0, 0, 40000, 126,0.000000 }, - {3613,3613, 0, 0, 3680, 3680,0.000000 }, - {3614,3614, 0, 0, 660, 660,0.000000 }, - {3615,3615, 0, 0, 40000, 206,0.000000 }, - {3616,3616, 0, 0, 40000, 106,0.000000 }, - {3617,3617, 0, 0, 546, 546,0.000000 }, - {3618,3618, 0, 0, 126, 6,0.000000 }, - {3619,3619, 0, 0, 40000, 1306,0.000000 }, - {3620,3620, 0, 0, 1240, 1240,0.000000 }, - {3621,3621, 0, 0, 1400, 1400,0.000000 }, - {3622,3622, 0, 0, 40000, 0,0.000000 }, - {3623,3623, 0, 0, 40000, 0,0.000000 }, - {3624,3624, 0, 0, 40000, 833,0.000000 }, - {3625,3625, 0, 0, 40000, 240,0.000000 }, - {3626,3626, 0, 0, 40000, 1973,0.000000 }, - {3627,3627, 0, 0, 4466, 4466,0.000000 }, - {3628,3628, 0, 0, 13, 13,0.000000 }, - {3629,3629, 0, 0, 40000, 2206,0.000000 }, - {3630,3630, 0, 0, 40000, 1180,0.000000 }, - {3631,3631, 0, 0, 4933, 4933,0.000000 }, - {3632,3632, 0, 0, 200, 200,0.000000 }, - {3633,3633, 0, 0, 1226, 1226,0.000000 }, - {3634,3634, 0, 0, 273, 273,0.000000 }, - {3635,3635, 0, 0, 353, 13,0.000000 }, - {3636,3636, 0, 0, 40000, 6,0.000000 }, - {3637,3637, 0, 0, 60, 60,0.000000 }, - {3638,3638, 0, 0, 160, 160,0.000000 }, - {3639,3639, 0, 0, 313, 313,0.000000 }, - {3640,3640, 0, 0, 46, 46,0.000000 }, - {3641,3641, 0, 0, 313, 313,0.000000 }, - {3642,3642, 0, 0, 40, 40,0.000000 }, - {3643,3643, 0, 0, 86, 86,0.000000 }, - {3644,3644, 0, 0, 46, 46,0.000000 }, - {3645,3645, 0, 0, 146, 146,0.000000 }, - {3646,3646, 0, 0, 146, 146,0.000000 }, - {3647,3647, 0, 0, 220, 220,0.000000 }, - {3648,3648, 0, 0, 86, 86,0.000000 }, - {3649,3649, 0, 0, 40000, 320,0.000000 }, - {3650,3650, 0, 0, 40000, 6,0.000000 }, - {3651,3651, 0, 0, 40000, 0,0.000000 }, - {3652,3652, 0, 0, 300, 300,0.000000 }, - {3653,3653, 0, 0, 2940, 2940,0.000000 }, - {3654,3654, 0, 0, 1233, 1233,0.000000 }, - {3655,3655, 0, 0, 3840, 3840,0.000000 }, - {3656,3656, 0, 0, 2280, 2280,0.000000 }, - {3657,3657, 0, 0, 1793, 1793,0.000000 }, - {3658,3658, 0, 0, 1120, 1120,0.000000 }, - {3659,3659, 0, 0, 1013, 1013,0.000000 }, - {3660,3660, 0, 0, 1233, 1233,0.000000 }, - {3661,3661, 0, 0, 600, 600,0.000000 }, - {3662,3662, 0, 0, 280, 280,0.000000 }, - {3663,3663, 0, 0, 266, 266,0.000000 }, - {3664,3664, 0, 0, 1740, 1740,0.000000 }, - {3665,3665, 0, 0, 246, 246,0.000000 }, - {3666,3666, 0, 0, 140, 140,0.000000 }, - {3667,3667, 0, 0, 1166, 1166,0.000000 }, - {3668,3668, 0, 0, 273, 273,0.000000 }, - {3669,3669, 0, 0, 40000, 0,0.000000 }, - {3670,3670, 0, 0, 40000, 0,0.000000 }, - {3671,3671, 0, 0, 313, 313,0.000000 }, - {3672,3672, 0, 0, 40000, 6,0.000000 }, - {3673,3673, 0, 0, 40000, 133,0.000000 }, - {3674,3674, 0, 0, 40000, 133,0.000000 }, - {3675,3675, 0, 0, 40000, 66,0.000000 }, - {3676,3676, 0, 0, 40000, 133,0.000000 }, - {3677,3677, 0, 0, 940, 940,0.000000 }, - {3678,3678, 0, 0, 760, 760,0.000000 }, - {3679,3679, 0, 0, 1200, 1200,0.000000 }, - {3680,3680, 0, 0, 566, 566,0.000000 }, - {3681,3681, 0, 0, 573, 573,0.000000 }, - {3682,3682, 0, 0, 40000, 0,0.000000 }, - {3683,3683, 0, 0, 1353, 1353,0.000000 }, - {3684,3684, 0, 0, 2226, 2226,0.000000 }, - {3685,3685, 0, 0, 866, 866,0.000000 }, - {3686,3686, 0, 0, 2293, 2293,0.000000 }, - {3687,3687, 0, 0, 2113, 2113,0.000000 }, - {3688,3688, 0, 0, 1280, 1280,0.000000 }, - {3689,3689, 0, 0, 886, 886,0.000000 }, - {3690,3690, 0, 0, 833, 833,0.000000 }, - {3691,3691, 0, 0, 886, 886,0.000000 }, - {3692,3692, 0, 0, 940, 940,0.000000 }, - {3693,3693, 0, 0, 40000, 260,0.000000 }, - {3694,3694, 0, 0, 166, 13,0.000000 }, - {3695,3695, 0, 0, 40000, 26,0.000000 }, - {3696,3696, 0, 0, 146, 146,0.000000 }, - {3697,3697, 0, 0, 40000, 86,0.000000 }, - {3698,3698, 0, 0, 940, 940,0.000000 }, - {3699,3699, 0, 0, 100, 100,0.000000 }, - {3700,3700, 0, 0, 513, 513,0.000000 }, - {3701,3701, 0, 0, 40000, 286,0.000000 }, - {3702,3702, 0, 0, 40000, 133,0.000000 }, - {3703,3703, 0, 0, 40000, 233,0.000000 }, - {3704,3704, 0, 0, 40000, 40,0.000000 }, - {3705,3705, 0, 0, 3413, 3413,0.000000 }, - {3706,3706, 0, 0, 3413, 3413,0.000000 }, - {3707,3707, 0, 0, 253, 253,0.000000 }, - {3708,3708, 0, 0, 60, 73,0.000000 }, - {3709,3709, 0, 0, 40000, 66,0.000000 }, - {3710,3710, 0, 0, 40000, 33,0.000000 }, - {3711,3711, 0, 0, 40000, 0,0.000000 }, - {3712,3712, 0, 0, 40000, 126,0.000000 }, - {3713,3713, 0, 0, 40000, 6,0.000000 }, - {3714,3714, 0, 0, 40000, 0,0.000000 }, - {3715,3715, 0, 0, 40000, 126,0.000000 }, - {3716,3716, 0, 0, 40000, 26,0.000000 }, - {3717,3717, 0, 0, 40000, 20,0.000000 }, - {3718,3718, 0, 0, 40000, 20,0.000000 }, - {3719,3719, 0, 0, 40000, 0,0.000000 }, - {3720,3720, 0, 0, 40000, 0,0.000000 }, - {3721,3721, 0, 0, 40000, 6,0.000000 }, - {3722,3722, 0, 0, 40000, 33,0.000000 }, - {3723,3723, 0, 0, 40000, 6,0.000000 }, - {3724,3724, 0, 0, 40000, 6,0.000000 }, - {3725,3725, 0, 0, 40000, 20,0.000000 }, - {3726,3726, 0, 0, 40000, 33,0.000000 }, - {3727,3727, 0, 0, 100, 100,0.000000 }, - {3728,3728, 0, 0, 40000, 26,0.000000 }, - {3729,3729, 0, 0, 40000, 26,0.000000 }, - {3730,3730, 0, 0, 40000, 53,0.000000 }, - {3731,3731, 0, 0, 40000, 0,0.000000 }, - {3732,3732, 0, 0, 40000, 0,0.000000 }, - {3733,3733, 0, 0, 40000, 26,0.000000 }, - {3734,3734, 0, 0, 40000, 13,0.000000 }, - {3735,3735, 0, 0, 40000, 6,0.000000 }, - {3736,3736, 0, 0, 3766, 3766,0.000000 }, - {3737,3737, 0, 0, 40000, 140,0.000000 }, - {3738,3738, 0, 0, 40000, 13,0.000000 }, - {3739,3739, 0, 0, 40000, 233,0.000000 }, - {3740,3740, 0, 0, 40000, 413,0.000000 }, - {3741,3741, 0, 0, 1873, 26,0.000000 }, - {3742,3742, 0, 0, 40000, 566,0.000000 }, - {3743,3743, 0, 0, 753, 753,0.000000 }, - {3744,3744, 0, 0, 1166, 13,0.000000 }, - {3745,3745, 0, 0, 40000, 566,0.000000 }, - {3746,3746, 0, 0, 40000, 53,0.000000 }, - {3747,3747, 0, 0, 1020, 1020,0.000000 }, - {3748,3748, 0, 0, 40000, 340,0.000000 }, - {3749,3749, 0, 0, 440, 440,0.000000 }, - {3750,3750, 0, 0, 40000, 106,0.000000 }, - {3751,3751, 0, 0, 2286, 2286,0.000000 }, - {3752,3752, 0, 0, 40000, 966,0.000000 }, - {3753,3753, 0, 0, 40000, 766,0.000000 }, - {3754,3754, 0, 0, 40000, 6,0.000000 }, - {3755,3755, 0, 0, 4933, 4933,0.000000 }, - {3756,3756, 0, 0, 1126, 1126,0.000000 }, - {3757,3757, 0, 0, 273, 273,0.000000 }, - {3758,3758, 0, 0, 546, 546,0.000000 }, - {3759,3759, 0, 0, 280, 280,0.000000 }, - {3760,3760, 0, 0, 40000, 6,0.000000 }, - {3761,3761, 0, 0, 40000, 6,0.000000 }, - {3762,3762, 0, 0, 40000, 0,0.000000 }, - {3763,3763, 0, 0, 1106, 1106,0.000000 }, - {3764,3764, 0, 0, 86, 86,0.000000 }, - {3765,3765, 0, 0, 280, 280,0.000000 }, - {3766,3766, 0, 0, 53, 53,0.000000 }, - {3767,3767, 0, 0, 40, 40,0.000000 }, - {3768,3768, 0, 0, 60, 60,0.000000 }, - {3769,3769, 0, 0, 253, 253,0.000000 }, - {3770,3770, 0, 0, 1213, 1213,0.000000 }, - {3771,3771, 0, 0, 293, 293,0.000000 }, - {3772,3772, 0, 0, 153, 153,0.000000 }, - {3773,3773, 0, 0, 4586, 4586,0.000000 }, - {3774,3774, 0, 0, 146, 146,0.000000 }, - {3775,3775, 0, 0, 40000, 0,0.000000 }, - {3776,3776, 0, 0, 146, 146,0.000000 }, - {3777,3777, 0, 0, 40000, 113,0.000000 }, - {3778,3778, 0, 0, 153, 153,0.000000 }, - {3779,3779, 0, 0, 1726, 13,0.000000 }, - { 738, 738, 44, 0, 40, 40,0.000000 }, - {3780,3780, 36, 0, 33, 33,0.000000 }, - {3781,3781, 32, 0, 6, 6,0.000000 }, - {2030,2030, 60, 0, 86, 86,0.000000 }, - {3782,3782, 24, 0, 6, 6,0.000000 }, - {3783,3783, 60, 0, 26, 26,0.000000 }, - {3784,3784, 44, 0, 140, 140,0.000000 }, - { 132, 132, 44, 0, 20, 20,0.000000 }, - {3785,3785, 47, 0, 153, 153,0.000000 }, - { 152, 152, 44, 0, 86, 86,0.000000 }, - {3784,3784, 50, 0, 160, 160,0.000000 }, - { 139, 139, 44, 0, 86, 86,0.000000 }, - {3784,3784, 54, 0, 160, 160,0.000000 }, - {3784,3784, 57, 0, 160, 160,0.000000 }, - {3786,3786, 60, 0, 606, 606,0.000000 }, - {3784,3784, 60, 0, 166, 166,0.000000 }, - {3787,3787, 60, 0, 606, 606,0.000000 }, - {3788,3788, 60, 0, 626, 626,0.000000 }, - {3789,3789, 60, 0, 626, 626,0.000000 }, - {3790,3790, 60, 0, 606, 606,0.000000 }, - {3791,3791, 44, 0, 300, 300,0.000000 }, - {2037,2037, 44, 0, 40, 40,0.000000 }, - { 144, 144, 44, 0, 40, 40,0.000000 }, - {2038,2038, 44, 0, 13, 13,0.000000 }, - {3792,3792, 44, 0, 33, 33,0.000000 }, - {3793,3793, 44, 0, 60, 60,0.000000 }, - {3794,3794, 45, 0, 80, 80,0.000000 }, - {3795,3795, 33, 0, 100, 100,0.000000 }, - {3796,3796, 56, 0, 153, 153,0.000000 }, - {3796,3796, 51, 0, 153, 153,0.000000 }, - {3797,3797, 44, 0, 40, 40,0.000000 }, - {3798,3798, 44, 0, 200, 200,0.000000 }, - {3534,3534, 56, 0, 73, 73,0.000000 }, - { 158, 158, 68, 0, 20, 20,0.000000 }, - {3799,3799, 51, 0, 160, 160,0.000000 }, - {3800,3800, 46, 0, 153, 153,0.000000 }, - {3801,3801, 44, 0, 160, 160,0.000000 }, - {3802,3802, 44, 0, 1233, 1233,0.000000 }, - { 152, 152, 45, 0, 80, 80,0.000000 }, - {3803,3803, 0, 0, 40000, 20,0.000000 }, - {3804,3804, 0, 0, 40000, 66,0.000000 }, - {3805,3805, 0, 0, 40000, 0,0.000000 }, - {3806,3806, 0, 0, 40000, 0,0.000000 }, - {3807,3807, 0, 0, 40000, 20,0.000000 }, - {3808,3808, 0, 0, 1226, 1226,0.000000 }, - {3809,3809, 0, 0, 546, 546,0.000000 }, - {3810,3810, 0, 0, 280, 280,0.000000 }, - {3811,3811, 0, 0, 60, 60,0.000000 }, - {3812,3812, 0, 0, 1213, 1213,0.000000 }, - {3780,3780, 45, 0, 440, 440,0.000000 }, - {3061,3061, 45, 0, 606, 606,0.000000 }, - {3813,3813, 60, 0, 20, 20,0.000000 }, - {3781,3781, 60, 0, 6, 6,0.000000 }, - {3814,3814, 44, 0, 173, 173,0.000000 }, - {3815,3815, 57, 0, 46, 46,0.000000 }, - {3816,3816, 56, 0, 73, 73,0.000000 }, - {3817,3817, 60, 0, 20, 20,0.000000 }, - {3818,3818, 60, 0, 20, 20,0.000000 }, - {3517,3517, 45, 0, 40, 40,0.000000 }, - {3819,3819, 0, 0, 820, 820,0.000000 }, - {3820,3820, 0, 0, 573, 573,0.000000 }, - {3821,3821, 0, 0, 473, 473,0.000000 }, - {3822,3822, 0, 0, 1020, 1020,0.000000 }, - {3823,3823, 0, 0, 40000, 393,0.000000 }, - {3824,3825, 0, 1, 40000, 266,0.078125 }, - {3826,3826, 0, 0, 3833, 13,0.000000 }, - {3827,3827, 0, 0, 40000, 406,0.000000 }, - {3828,1172, 0, 1, 40000, 320,0.156250 }, - {3829,3829, 0, 0, 40000, 13,0.000000 }, - {3830,3830, 0, 0, 120, 120,0.000000 }, - {3831,3831, 32, 0, 20, 20,0.000000 }, - {3832,3832, 36, 0, 46, 46,0.000000 }, - {3833,3833, 88, 0, 93, 93,0.000000 }, - {3834,3834, 0, 0, 1660, 1660,0.000000 }, - {3835,3835, 0, 0, 1746, 1746,0.000000 }, - {3836,3836, 0, 0, 1980, 1980,0.000000 }, - {3837,3837, 0, 0, 1553, 1553,0.000000 }, - {3838,3838, 0, 0, 1233, 1233,0.000000 }, - {3839,3839, 0, 0, 1980, 1980,0.000000 }, - {3840,3840, 0, 0, 940, 940,0.000000 }, - {3841,3841, 0, 0, 1740, 1740,0.000000 }, - {3842,3842, 0, 0, 40000, 133,0.000000 }, - {3843,3843, 0, 0, 40000, 26,0.000000 }, - {3844,3844, 0, 0, 40000, 60,0.000000 }, - {3845,3845, 0, 0, 40000, 320,0.000000 }, - {3846,3846, 0, 0, 40000, 53,0.000000 }, - {3847,3847, 0, 0, 40000, 160,0.000000 }, - {3848,3848, 0, 0, 40000, 106,0.000000 }, - {3849,3849, 0, 0, 1026, 1026,0.000000 }, - {3850,3850, 0, 0, 1826, 1826,0.000000 }, - {3851,3851, 0, 0, 1813, 1813,0.000000 }, - {3852,3852, 0, 0, 1013, 1013,0.000000 }, - {3853,3853, 0, 0, 40000, 0,0.000000 }, - {3854,3854, 0, 0, 40000, 53,0.000000 }, - {3855,3855, 0, 0, 40000, 53,0.000000 }, - {3856,3856, 0, 0, 4200, 4200,0.000000 }, - {3857,3857, 0, 0, 40000, 106,0.000000 }, - {3858,3858, 0, 0, 1746, 1746,0.000000 }, - {3859,3859, 0, 0, 40000, 120,0.000000 }, - {3860,3860, 0, 0, 2400, 2400,0.000000 }, - {3861,3861, 0, 0, 4606, 4606,0.000000 }, - {3862,3862, 0, 0, 1740, 1740,0.000000 }, - {3863,3863, 0, 0, 40000, 66,0.000000 }, - {3864,3864, 0, 0, 40000, 46,0.000000 }, - {3865,3865, 0, 0, 40000, 66,0.000000 }, - {3866,3866, 0, 0, 40000, 26,0.000000 }, - {3867,3867, 0, 0, 40000, 293,0.000000 }, - {3868,3868, 0, 0, 40000, 133,0.000000 }, - {3869,3869, 0, 0, 333, 333,0.000000 }, - {3870,3870, 0, 0, 993, 993,0.000000 }, - {3871,3871, 0, 0, 40000, 280,0.000000 }, - {3872,3872, 0, 0, 1766, 13,0.000000 }, - {3873,3873, 0, 0, 40000, 820,0.000000 }, - {3874,3874, 0, 0, 40000, 286,0.000000 }, - {3875,3875, 0, 0, 40000, 580,0.000000 }, - {3876,3876, 0, 0, 2300, 2300,0.000000 }, - {3877,3877, 0, 0, 40000, 146,0.000000 }, - {3878,3878, 0, 0, 40000, 6,0.000000 }, - {3879,3879, 0, 0, 40000, 66,0.000000 }, - {3880,3880, 0, 0, 40000, 6,0.000000 }, - {3881,3881, 0, 0, 40000, 6,0.000000 }, - {3882,3882, 0, 0, 40000, 126,0.000000 }, - {3883,3883, 0, 0, 40000, 33,0.000000 }, - {3884,3884, 0, 0, 40000, 53,0.000000 }, - {3885,3885, 0, 0, 40000, 93,0.000000 }, - {3886,3886, 0, 0, 40000, 73,0.000000 }, - {3887,3887, 0, 0, 40000, 66,0.000000 }, - {3888,3888, 0, 0, 40000, 86,0.000000 }, - {3889,3889, 0, 0, 40000, 46,0.000000 }, - {3890,3890, 0, 0, 3940, 13,0.000000 }, - {3891,3891, 0, 0, 40000, 33,0.000000 }, - {3892,3892, 0, 0, 40000, 53,0.000000 }, - {3893,3893, 0, 0, 40000, 53,0.000000 }, - {3894,3894, 0, 0, 40000, 73,0.000000 }, - {3895,3895, 0, 0, 40000, 126,0.000000 }, - {3896,3896, 0, 0, 40000, 60,0.000000 }, - {3897,3897, 0, 0, 40000, 106,0.000000 }, - {3898,3898, 0, 0, 40000, 6,0.000000 }, - {3899,3899, 0, 0, 40000, 266,0.000000 }, - {3900,3900, 0, 0, 40000, 53,0.000000 }, - {3901,3901, 0, 0, 40000, 233,0.000000 }, - {3902,3902, 0, 0, 1660, 180,0.000000 }, - {3903,3903, 0, 0, 40000, 566,0.000000 }, - {3904,3904, 0, 0, 40000, 100,0.000000 }, - {3905,3905, 0, 0, 593, 13,0.000000 }, - {3906,3906, 0, 0, 40000, 173,0.000000 }, - {3907,3907, 0, 0, 40000, 53,0.000000 }, - {3908,3908, 0, 0, 40000, 106,0.000000 }, - {3909,3909, 0, 0, 2133, 2133,0.000000 }, - {3910,3910, 0, 0, 40000, 846,0.000000 }, - {3911,3911, 0, 0, 40000, 773,0.000000 }, - {3912,3912, 0, 0, 1066, 1066,0.000000 }, - {3913,3913, 0, 0, 40000, 73,0.000000 }, - {3914,3914, 0, 0, 40000, 86,0.000000 }, - {3915,3915, 0, 0, 40000, 46,0.000000 }, - {3916,3916, 0, 0, 1126, 1126,0.000000 }, - {3917,3917, 0, 0, 40000, 13,0.000000 }, - {3918,3918, 0, 0, 300, 300,0.000000 }, - {3919,3919, 0, 0, 146, 146,0.000000 }, - {3920,3920, 0, 0, 140, 140,0.000000 }, - {3921,3921, 0, 0, 1920, 1920,0.000000 }, - {3922,3922, 0, 0, 40000, 0,0.000000 }, - {3923,3923, 0, 0, 533, 533,0.000000 }, - {3924,3924, 0, 0, 486, 486,0.000000 }, - {3925,3925, 0, 0, 940, 940,0.000000 }, - {3926,3926, 0, 0, 600, 600,0.000000 }, - {3927,3927, 0, 0, 253, 253,0.000000 }, - {3928,3928, 0, 0, 380, 73,0.000000 }, - {3929,3929, 0, 0, 40, 40,0.000000 }, - {3930,3930, 0, 0, 40000, 20,0.000000 }, - {3931,3931, 0, 0, 40000, 13,0.000000 }, - {3932,3932, 0, 0, 4600, 4600,0.000000 }, - {3933,3933, 0, 0, 4820, 4820,0.000000 }, - { 523, 523, 0, 0, 46, 46,0.000000 }, - {3934,3934, 0, 0, 66, 66,0.000000 }, - {3935,3935, 0, 0, 53, 53,0.000000 }, - {3936,3936, 48, 0, 26, 26,0.000000 }, - {3937,3937, 27, 0, 53, 53,0.000000 }, - {3938,3938, 40, 0, 40, 40,0.000000 }, - {3939,3939, 48, 0, 13, 13,0.000000 }, - {3938,3938, 45, 0, 46, 46,0.000000 }, - {3940,3940, 48, 0, 26, 26,0.000000 }, - {3938,3938, 47, 0, 66, 66,0.000000 }, - {3941,3941, 48, 0, 13, 13,0.000000 }, - {3938,3938, 49, 0, 73, 73,0.000000 }, - {3938,3938, 53, 0, 80, 80,0.000000 }, - {3938,3938, 56, 0, 66, 66,0.000000 }, - { 129, 129, 52, 0, 73, 73,0.000000 }, - { 130, 130, 48, 0, 40, 40,0.000000 }, - { 129, 129, 58, 0, 73, 73,0.000000 }, - { 132, 132, 47, 0, 20, 20,0.000000 }, - { 492, 492, 43, 0, 26, 26,0.000000 }, - { 132, 132, 49, 0, 20, 20,0.000000 }, - { 132, 132, 51, 0, 20, 20,0.000000 }, - { 132, 132, 54, 0, 20, 20,0.000000 }, - { 132, 132, 57, 0, 13, 13,0.000000 }, - { 492, 492, 72, 0, 140, 140,0.000000 }, - { 137, 137, 76, 0, 600, 600,0.000000 }, - { 138, 138, 84, 0, 246, 246,0.000000 }, - { 139, 139, 36, 0, 113, 113,0.000000 }, - { 140, 140, 76, 0, 586, 586,0.000000 }, - { 141, 141, 84, 0, 60, 60,0.000000 }, - { 135, 135, 83, 0, 413, 413,0.000000 }, - { 142, 142, 84, 0, 106, 106,0.000000 }, - {3942,3942, 24, 0, 600, 600,0.000000 }, - { 137, 137, 77, 0, 606, 606,0.000000 }, - { 144, 144, 60, 0, 40, 40,0.000000 }, - { 145, 145, 65, 0, 13, 13,0.000000 }, - { 146, 146, 59, 0, 40, 40,0.000000 }, - { 147, 147, 51, 0, 40, 40,0.000000 }, - { 148, 148, 45, 0, 46, 46,0.000000 }, - { 149, 149, 71, 0, 140, 140,0.000000 }, - { 150, 150, 60, 0, 146, 146,0.000000 }, - { 151, 151, 58, 0, 153, 153,0.000000 }, - { 152, 152, 53, 0, 80, 80,0.000000 }, - { 153, 153, 64, 0, 13, 13,0.000000 }, - { 154, 154, 71, 0, 273, 273,0.000000 }, - { 156, 156, 61, 0, 53, 53,0.000000 }, - { 158, 158, 48, 0, 40, 40,0.000000 }, - { 159, 159, 69, 0, 20, 20,0.000000 }, - { 160, 160, 68, 0, 20, 20,0.000000 }, - { 161, 161, 63, 0, 113, 113,0.000000 }, - { 162, 162, 74, 0, 293, 293,0.000000 }, - { 163, 163, 60, 0, 113, 113,0.000000 }, - { 164, 164, 80, 0, 440, 440,0.000000 }, - { 165, 165, 64, 0, 40, 40,0.000000 }, - { 166, 166, 69, 0, 286, 286,0.000000 }, - { 167, 167, 73, 0, 126, 126,0.000000 }, - { 168, 168, 75, 0, 20, 20,0.000000 }, - { 169, 169, 68, 0, 33, 33,0.000000 }, - { 131, 131, 48, 0, 93, 93,0.000000 }, - {3061,3061, 53, 0, 833, 833,0.000000 }, - {3943,3944, 0, 0, 546, 546,0.000000 }, - {3945,3946, 0, 0, 1813, 1813,0.000000 }, - { 174,3947, 0, 0, 1260, 1260,0.000000 }, - {3948,3949, 0, 0, 160, 160,0.000000 }, - { 9,3950, 0, 0, 1100, 1100,0.000000 }, - {3951,3952, 0, 0, 3360, 3360,0.000000 }, - {3953,3954, 0, 0, 1720, 1720,0.000000 }, - { 15,3955, 0, 0, 226, 226,0.000000 }, - {3956,3957, 0, 0, 40000, 6,0.000000 }, - {3958,3959, 0, 0, 40000, 6,0.000000 }, - {3960,3961, 0, 0, 40000, 186,0.000000 }, - {3962,3963, 0, 0, 40000, 6,0.000000 }, - {3964,3965, 0, 0, 146, 146,0.000000 }, - {3966,3965, 0, 0, 146, 146,0.000000 }, - { 31,3967, 0, 0, 3386, 3386,0.000000 }, - {3968,3969, 0, 0, 3520, 3520,0.000000 }, - {3970,3971, 0, 0, 126, 0,0.000000 }, - {3972,3971, 0, 0, 126, 0,0.000000 }, - {3973,3974, 0, 0, 1013, 1013,0.000000 }, - {3975,3976, 0, 0, 3733, 3733,0.000000 }, - {3977,3976, 0, 0, 3733, 3733,0.000000 }, - {3978,3979, 0, 0, 3020, 3020,0.000000 }, - {3980,3981, 0, 0, 686, 686,0.000000 }, - {3982,3983, 0, 0, 40000, 46,0.000000 }, - {3984,3985, 0, 0, 40000, 373,0.000000 }, - { 54,3986, 0, 0, 340, 340,0.000000 }, - {3987,3988, 0, 0, 1213, 6,0.000000 }, - {3989,3990, 0, 0, 40000, 53,0.000000 }, - {3991, 253, 0, 0, 40000, 126,0.000000 }, - {3992,3992, 0, 0, 40, 40,0.000000 }, - {3993,3993, 0, 0, 40000, 53,0.000000 }, - {3994,3995, 0, 0, 40000, 13,0.000000 }, - {3996,3997, 0, 0, 40000, 40,0.000000 }, - {3998,3999, 0, 0, 40000, 13,0.000000 }, - {1503,4000, 0, 0, 40000, 33,0.000000 }, - { 88,4001, 0, 0, 40000, 500,0.000000 }, - {3743,4002, 0, 0, 900, 900,0.000000 }, - { 92,4003, 0, 0, 1720, 13,0.000000 }, - { 93,4004, 0, 0, 1060, 80,0.000000 }, - { 94,4005, 0, 0, 40000, 53,0.000000 }, - { 96,4006, 0, 0, 1913, 533,0.000000 }, - { 103,4007, 0, 0, 1813, 1813,0.000000 }, - { 104,4008, 0, 0, 846, 846,0.000000 }, - { 105,4009, 0, 0, 900, 900,0.000000 }, - { 107,4010, 0, 0, 300, 300,0.000000 }, - { 108,4011, 0, 0, 40000, 6,0.000000 }, - { 110,4012, 0, 0, 40000, 6,0.000000 }, - { 111,4013, 0, 0, 1126, 1126,0.000000 }, - {4014,4015, 0, 0, 140, 140,0.000000 }, - { 115,4016, 0, 0, 146, 146,0.000000 }, - { 118,4017, 0, 0, 2280, 2280,0.000000 }, - { 119,4018, 0, 0, 286, 286,0.000000 }, - { 120,4019, 0, 0, 586, 586,0.000000 }, - { 121,4020, 0, 0, 4426, 4426,0.000000 }, - { 123,4021, 0, 0, 193, 193,0.000000 }, - { 124,4022, 0, 0, 146, 260,0.000000 }, - { 125,4023, 0, 0, 40000, 773,0.000000 }, - {4024,4024, 35, 0, 40, 40,0.000000 }, - {4025,4026, 38, 1, 93, 93,0.000000 }, - {4027,4028, 38, 1, 120, 120,0.000000 }, - {4029,4030, 48, 1, 73, 73,-1.906250 }, - {4031,4031, 51, 0, 26, 26,0.000000 }, - {4032,4033, 48, 1, 293, 293,-1.906250 }, - {4034,4034, 61, 1, 1873, 1873,0.093750 }, - {3369,1557, 70, 0, 906, 906,0.000000 }, - {4035,4036, 79, 1, 293, 293,0.078125 }, - {4037,4037, 62, 0, 1726, 1726,0.000000 }, - {4038,4039, 67, 1, 240, 240,0.078125 }, - {4040,4040, 62, 1, 2040, 2040,0.093750 }, - {4041,4042, 54, 1, 80, 80,0.000000 }, - {4041,4043, 48, 1, 80, 80,0.000000 }, - { 389, 389, 42, 0, 180, 180,0.000000 }, - {4044,4045, 48, 1, 80, 80,0.000000 }, - {4046,4047, 48, 1, 53, 53,0.000000 }, - {4048,4048, 16, 0, 20, 20,0.000000 }, - {4049,4049, 16, 0, 146, 146,0.000000 }, - {4050,4051, 64, 0, 646, 646,0.000000 }, - { 844, 844,244, 0, 13, 13,0.000000 }, - { 855, 855,244, 0, 246, 6,0.000000 }, - { 880, 880,232, 0, 46, 46,0.000000 }, - { 882, 882,220, 0, 5433, 5433,0.000000 }, - { 887, 887, 35, 0, 46, 46,0.000000 }, - { 884, 884, 35, 0, 73, 73,0.000000 }, - { 885, 885, 35, 0, 73, 73,0.000000 }, - { 886, 886, 35, 0, 20, 20,0.000000 }, - { 361, 361, 35, 0, 113, 113,0.000000 }, - { 767, 767, 35, 0, 760, 760,0.000000 }, - { 888, 888, 35, 0, 40, 40,0.000000 }, - {2141,2141, 35, 0, 53, 53,0.000000 }, - { 891, 891, 35, 0, 106, 106,0.000000 }, - {2142,2142, 35, 0, 53, 53,0.000000 }, - {2143,2143, 35, 0, 73, 73,0.000000 }, - {2144,2144, 35, 0, 800, 800,0.000000 }, - {2145,2145, 35, 0, 420, 420,0.000000 }, - { 376, 376, 35, 0, 146, 146,0.000000 }, - { 895, 895, 35, 0, 126, 126,0.000000 }, - {2146,2146, 35, 0, 100, 100,0.000000 }, - { 382, 382, 35, 0, 20, 20,0.000000 }, - {2147,2147, 35, 0, 20, 20,0.000000 }, - { 898, 898, 35, 0, 60, 60,0.000000 }, - { 899, 899, 35, 0, 206, 206,0.000000 }, - { 900, 900, 35, 0, 193, 193,0.000000 }, - { 871, 871, 35, 0, 120, 120,0.000000 }, - { 388, 388, 35, 0, 73, 73,0.000000 }, - { 901, 901, 35, 0, 173, 173,0.000000 }, - { 902, 902, 35, 0, 1006, 1006,0.000000 }, - { 903, 903, 35, 0, 40, 40,0.000000 }, - {3500,3500, 35, 0, 5233, 6,0.000000 }, - {4052,4052, 0, 0, 1400, 1400,0.000000 }, - {4053,4053, 0, 0, 1206, 1206,0.000000 }, - {4054,4054, 0, 0, 40000, 46,0.000000 }, - {4055,4055, 0, 0, 40000, 26,0.000000 }, - {4056,4056, 0, 0, 3600, 3600,0.000000 }, - {4057,4057, 0, 0, 40000, 6,0.000000 }, - {4058,4058, 0, 0, 960, 960,0.000000 }, - {4059,4059, 0, 0, 80, 80,0.000000 }, - {4060,4060, 0, 0, 40000, 20,0.000000 }, - {4061,4061, 0, 0, 40000, 20,0.000000 }, - {4062,4062, 0, 0, 4473, 4473,0.000000 }, - {4063,4063, 0, 0, 380, 6,0.000000 }, - {4064,4064, 0, 0, 40000, 20,0.000000 }, - {4065,4065, 0, 0, 4593, 4593,0.000000 }, - {4066,4066, 0, 0, 40000, 20,0.000000 }, - {4067,4067, 0, 0, 40000, 0,0.000000 }, - {4068,4068, 0, 0, 40, 40,0.000000 }, - {4069,4069, 0, 0, 60, 60,0.000000 }, - {4070,4070, 0, 0, 100, 100,0.000000 }, - {4071,4071, 0, 0, 40000, 40,0.000000 }, - {4072,4072, 0, 0, 126, 126,0.000000 }, - {4073,4073, 0, 0, 40, 40,0.000000 }, - {4074,4074, 0, 0, 40000, 0,0.000000 }, - {4075,4075, 0, 0, 4193, 4193,0.000000 }, - {4076,4076, 0, 0, 806, 0,0.000000 }, - {4077,4077, 0, 0, 526, 526,0.000000 }, - {4078,4078, 0, 0, 40000, 73,0.000000 }, - {4079,4079, 0, 0, 40000, 6,0.000000 }, - {4080,4080, 0, 0, 40000, 153,0.000000 }, - {4081,4081, 0, 0, 40000, 0,0.000000 }, - {4082,4082, 0, 0, 40, 6,0.000000 }, - {4083,4083, 0, 0, 3400, 0,0.000000 }, - {4084,4084, 0, 0, 2280, 0,0.000000 }, - {4085,4085, 0, 0, 40000, 426,0.000000 }, - {4086,4086, 0, 0, 1206, 1206,0.000000 }, - { 127, 127, 36, 0, 20, 20,0.000000 }, - {4087,4087, 36, 0, 6, 6,0.000000 }, - {2030,2030, 36, 0, 93, 93,0.000000 }, - {3782,3782, 48, 0, 6, 6,0.000000 }, - {3783,3783, 36, 0, 33, 33,0.000000 }, - {4088,4088, 48, 0, 246, 246,0.000000 }, - { 132, 132, 69, 0, 13, 13,0.000000 }, - {4088,4088, 52, 0, 360, 360,0.000000 }, - { 152, 152, 48, 0, 86, 86,0.000000 }, - {4088,4088, 55, 0, 493, 493,0.000000 }, - { 139, 139, 57, 0, 93, 93,0.000000 }, - {4088,4088, 58, 0, 560, 560,0.000000 }, - {4088,4088, 60, 0, 580, 580,0.000000 }, - {4089,4089, 62, 0, 840, 840,0.000000 }, - {4088,4088, 63, 0, 626, 626,0.000000 }, - { 134, 134, 70, 0, 140, 140,0.000000 }, - {4090,4090, 70, 0, 286, 286,0.000000 }, - {4091,4091, 53, 0, 613, 613,0.000000 }, - {3516,3516, 48, 0, 40, 40,0.000000 }, - {4092,4092, 84, 0, 420, 420,0.000000 }, - {4093,4093, 43, 0, 160, 160,0.000000 }, - {4094,4094, 56, 0, 326, 326,0.000000 }, - {3791,3791, 24, 0, 140, 140,0.000000 }, - { 134, 134, 65, 0, 160, 160,0.000000 }, - { 146, 146, 48, 0, 40, 40,0.000000 }, - { 146, 146, 54, 0, 40, 40,0.000000 }, - {4095,4095, 42, 0, 46, 46,0.000000 }, - {4095,4095, 39, 0, 46, 46,0.000000 }, - {3816,3816, 52, 0, 106, 106,0.000000 }, - {4096,4096, 52, 0, 200, 200,0.000000 }, - { 158, 158, 60, 0, 33, 33,0.000000 }, - { 158, 158, 66, 0, 33, 33,0.000000 }, - { 158, 158, 59, 0, 33, 33,0.000000 }, - {3538,3538, 91, 0, 273, 273,0.000000 }, - {3547,3547,109, 0, 1780, 1780,0.000000 }, - {4097,4097, 79, 0, 126, 126,0.000000 }, - {4098,4098, 0, 0, 3413, 3413,0.000000 }, - {4099,4100, 0, 1, 1613, 1613,0.031250 }, - {4101,4102, 0, 1, 2146, 2146,0.031250 }, - {4103,4104, 0, 1, 1646, 1646,0.046875 }, - {4105,4106, 0, 1, 1900, 1900,0.156250 }, - {4107,4108, 0, 1, 1473, 1473,0.046875 }, - {4109,4110, 0, 1, 1020, 1020,0.062500 }, - {4111,4112, 0, 1, 2126, 2126,0.000000 }, - {4113,4114, 0, 1, 1740, 1740,0.000000 }, - {4115,4116, 0, 1, 993, 993,0.000025 }, - {4117,4118, 0, 1, 886, 886,0.000000 }, - {4119,4120, 0, 1, 1153, 1153,0.046875 }, - {4121,4122, 0, 1, 1420, 1420,0.000000 }, - {4123,4124, 0, 1, 193, 193,0.000000 }, - {4125,4126, 0, 1, 406, 406,0.000000 }, - {4127,4128, 0, 1, 1400, 1400,0.031250 }, - {4129,4129, 0, 1, 980, 980,0.031250 }, - {4130,4131, 0, 1, 40000, 6,0.156250 }, - {4132,4133, 0, 1, 40, 13,0.078125 }, - {4134,4135, 0, 1, 7180, 13,0.156250 }, - {4136,4137, 0, 1, 40000, 180,0.031250 }, - {4138,4139, 0, 1, 40000, 46,0.062500 }, - {4140,4141, 0, 1, 40000, 46,0.140625 }, - {4142,4143, 0, 1, 40000, 6,0.000000 }, - {4144,4145, 0, 1, 40000, 153,0.109375 }, - {4146,4147, 0, 1, 920, 920,0.000000 }, - {4148,4149, 0, 1, 653, 653,0.000025 }, - {4150,4151, 0, 1, 633, 633,0.000000 }, - {4152,4153, 0, 1, 893, 893,0.046875 }, - {4154,4155, 0, 1, 440, 440,0.000000 }, - {4156,4157, 0, 1, 40000, 60,-1.906250 }, - {4158,4159, 0, 1, 40000, 60,-1.906250 }, - {4160,4161, 0, 1, 2033, 2033,0.234375 }, - {4162,4163, 0, 1, 1900, 1900,0.031250 }, - {4164,4165, 0, 1, 1453, 1453,0.000000 }, - {4166,4167, 0, 1, 2186, 2186,0.000000 }, - {4168,4169, 0, 1, 1933, 1933,0.046875 }, - {4170,4171, 0, 1, 633, 633,0.000000 }, - {4172,4173, 0, 1, 486, 486,0.000000 }, - {4174,4174, 0, 0, 313, 313,0.000000 }, - {4175,4176, 0, 1, 2533, 2533,0.078125 }, - {4177,4178, 0, 1, 2040, 13,0.000000 }, - {4179,4179, 0, 0, 40000, 66,0.000000 }, - {4180,4181, 0, 1, 40000, 60,0.000025 }, - {4182,4182, 0, 0, 40000, 133,0.000000 }, - {4183,4184, 0, 1, 40000, 173,0.078125 }, - {4185,4186, 0, 1, 333, 333,0.109375 }, - {4187,4188, 0, 1, 1813, 1813,0.031250 }, - {4189,4190, 0, 1, 1473, 1473,0.031250 }, - {4191,4192, 0, 1, 40000, 213,0.062500 }, - {4193,4194, 0, 1, 40000, 500,-0.062500 }, - {4195,4195, 0, 1, 40000, 326,0.109375 }, - {4196,4196, 0, 1, 40000, 406,0.109375 }, - {4197,4198, 0, 1, 40000, 280,0.140625 }, - {4199,4200, 0, 1, 40000, 53,0.140625 }, - {4201,4202, 0, 1, 40000, 286,0.156250 }, - {4203,4204, 0, 1, 206, 206,0.125000 }, - {4205,4206, 0, 1, 40000, 26,0.000000 }, - {4207,4208, 0, 1, 40000, 20,0.031250 }, - {4209,4209, 0, 0, 40000, 6,0.000000 }, - {4210,4210, 0, 0, 40000, 20,0.000000 }, - {4211,4212, 0, 1, 40000, 160,0.031250 }, - {4213,4214, 0, 1, 40000, 73,0.062500 }, - {4215,4216, 0, 1, 2526, 2526,0.093750 }, - {4217,4217, 0, 1, 5153, 5153,0.125000 }, - {4218,4219, 0, 1, 40000, 73,0.000000 }, - {4220,4220, 0, 0, 40000, 60,0.000000 }, - {4221,4221, 0, 0, 40000, 0,0.000000 }, - {4222,4222, 0, 0, 40000, 0,0.000000 }, - {4223,4224, 0, 1, 40000, 73,0.000000 }, - {4225,4225, 0, 0, 40000, 33,0.000000 }, - {4226,4226, 0, 0, 40000, 6,0.000000 }, - {4227,4228, 0, 1, 40000, 40,0.000000 }, - {4229,4229, 0, 0, 40000, 0,0.000000 }, - {4230,4230, 0, 0, 40000, 6,0.000000 }, - {4231,4231, 0, 0, 40000, 33,0.000000 }, - {4232,4233, 0, 1, 40000, 53,0.031250 }, - {4234,4235, 0, 1, 40000, 20,0.046875 }, - {4236,4237, 0, 1, 420, 420,0.031250 }, - {4238,4238, 0, 0, 40000, 106,0.000000 }, - {4239,4239, 0, 0, 40000, 6,0.000000 }, - {4240,4241, 0, 1, 40000, 6,0.125000 }, - {4242,4243, 0, 1, 40000, 13,0.109375 }, - {4244,4245, 0, 1, 40000, 53,0.109375 }, - {4246,4247, 0, 1, 226, 6,-0.031250 }, - {4248,4248, 0, 0, 40000, 6,0.000000 }, - {4249,4250, 0, 1, 40000, 133,0.156250 }, - {4251,4252, 0, 1, 4186, 13,0.125000 }, - {4253,4254, 0, 1, 40000, 26,0.031250 }, - {4255,4256, 0, 1, 40000, 660,0.078125 }, - {4257,4258, 0, 1, 846, 66,0.109375 }, - {4259,4260, 0, 1, 1293, 80,0.078125 }, - {4261,4262, 0, 1, 40000, 300,0.140625 }, - {4263,4264, 0, 1, 2040, 2040,0.109375 }, - {4265,4266, 0, 1, 1360, 1360,0.062500 }, - {4267,4268, 0, 1, 40000, 433,0.093750 }, - {4269,4270, 0, 1, 40000, 533,0.109375 }, - {4271,4272, 0, 1, 826, 826,0.093750 }, - {4273,4274, 0, 1, 40000, 926,0.125000 }, - {4275,4275, 0, 1, 886, 886,0.109375 }, - {4276,4277, 0, 1, 2186, 2186,-0.046875 }, - {4278,4279, 0, 1, 1486, 1486,0.125000 }, - {4280,4281, 0, 1, 40000, 393,-0.078125 }, - {4282,4283, 0, 1, 40000, 1166,0.140625 }, - {4284,4285, 0, 1, 360, 360,0.078125 }, - {4286,4287, 0, 1, 1693, 1693,0.031250 }, - {4288,4289, 0, 1, 760, 760,0.000000 }, - {4290,4291, 0, 1, 126, 126,0.031250 }, - {4292,4292, 0, 0, 300, 300,0.000000 }, - {4293,4294, 0, 1, 280, 280,0.000000 }, - {4295,4296, 0, 1, 40000, 26,0.062500 }, - {4297,4297, 0, 0, 40000, 66,0.000000 }, - {4298,4298, 0, 0, 40000, 53,0.000000 }, - {4299,4299, 0, 0, 1940, 1940,0.000000 }, - {4300,4300, 0, 0, 86, 86,0.000000 }, - {4301,4302, 0, 1, 280, 280,0.031250 }, - {4303,4303, 0, 0, 40, 40,0.000000 }, - {4304,4305, 0, 1, 53, 53,0.000000 }, - {4306,4307, 0, 1, 140, 140,0.000000 }, - {4308,4309, 0, 1, 26, 26,0.000000 }, - {4310,4311, 0, 1, 2153, 2153,0.109375 }, - {4312,4312, 0, 0, 293, 293,0.000000 }, - {4313,4314, 0, 1, 993, 26,0.000000 }, - {4315,4316, 0, 1, 5613, 5613,0.000000 }, - {4317,4317, 0, 0, 220, 220,0.000000 }, - {4318,4319, 0, 1, 10306, 526,0.000000 }, - {4320,4321, 0, 1, 1486, 13,0.000000 }, - {4322,4323, 0, 1, 40000, 660,0.000000 }, - {4324,4324, 0, 0, 120, 120,0.000000 }, - {4325,4325, 34, 0, 40, 40,0.000000 }, - {4326,4326, 28, 0, 73, 73,0.000000 }, - {4327,4328, 39, 1, 233, 233,0.000000 }, - {4327,4328, 33, 1, 193, 193,0.000000 }, - {4329,4330, 63, 1, 33, 33,0.000000 }, - {4331,4331, 15, 0, 13, 13,0.000000 }, - {4332,4332, 36, 0, 13, 13,0.000000 }, - {4332,4333, 36, 1, 133, 133,0.406250 }, - {4334,4335, 25, 1, 13, 13,0.000000 }, - {4336,4335, 25, 1, 33, 33,0.000000 }, - {4337,4338, 61, 1, 40, 40,0.000000 }, - {4339,4340, 37, 1, 53, 53,0.000000 }, - {4341,4342, 15, 1, 320, 320,0.000000 }, - {4343,4344, 48, 1, 73, 73,-1.906250 }, - {4341,4345, 19, 1, 320, 320,0.000000 }, - {4346,4346, 48, 0, 53, 53,0.000000 }, - {4341,4342, 22, 1, 353, 353,0.000000 }, - {4341,4342, 24, 1, 360, 360,0.000000 }, - {4341,4347, 27, 1, 393, 393,0.000000 }, - {4341,4342, 31, 1, 380, 380,0.000000 }, - {4348,4349, 60, 1, 246, 246,0.031250 }, - {4350,4350, 70, 0, 340, 340,0.000000 }, - {4351,4352, 80, 1, 106, 106,0.125000 }, - {4353,4353, 58, 0, 73, 73,0.000000 }, - {4354,4355, 31, 1, 313, 313,0.000000 }, - {4356,4356, 61, 0, 253, 253,0.000000 }, - {4357,4358, 41, 1, 100, 100,0.000000 }, - {4359,4360, 35, 1, 160, 160,0.000000 }, - {4361,4362, 29, 1, 40, 40,0.000000 }, - {4363,4364, 41, 1, 166, 166,0.000000 }, - {4363,4364, 37, 1, 160, 160,0.000000 }, - {4365,4366, 54, 1, 80, 80,0.000000 }, - {4365,4367, 48, 1, 80, 80,0.000000 }, - {4368,4369, 77, 1, 53, 53,0.000000 }, - {4370,4371, 72, 1, 46, 46,0.000000 }, - {4372,4372, 40, 0, 140, 140,0.000000 }, - {4373,4373, 38, 0, 73, 73,0.000000 }, - {4374,4374, 36, 0, 533, 533,0.000000 }, - {4375,4376, 60, 1, 26, 26,0.000000 }, - {4376,4377, 60, 1, 26, 26,0.000000 }, - {4378,4378, 73, 0, 60, 60,0.000000 }, - {4379,4380, 68, 1, 40, 40,0.000000 }, - {4381,4382, 18, 1, 60, 60,0.000000 }, - {4383,4384, 18, 1, 106, 106,0.000000 }, - {4385,4385, 90, 0, 80, 80,0.000000 }, - {4386,4386, 90, 0, 306, 306,0.000000 }, - {4387,4388, 64, 1, 233, 233,0.031250 }, - {4389,4390, 80, 1, 140, 140,0.031250 }, - {4391,4392, 64, 1, 606, 606,0.000000 }, - {4393,4393, 67, 0, 20, 20,0.000000 }, - {4394,4395, 50, 1, 53, 53,0.000000 }, - {4396,4396, 36, 0, 66, 66,0.000000 }, - {4397,4397, 0, 0, 40000, 20,0.000000 }, - {4398,4398, 0, 0, 40000, 0,0.000000 }, - {4399,4399, 0, 0, 360, 360,0.000000 }, - {4400,4400, 0, 0, 586, 586,0.000000 }, - {4401,4401, 0, 0, 40000, 0,0.000000 }, - {4402,4402, 0, 0, 40000, 0,0.000000 }, - {4403,4403, 0, 0, 40000, 0,0.000000 }, - {4404,4404, 0, 0, 40000, 6,0.000000 }, - {4405,4405, 0, 0, 40000, 0,0.000000 }, - {4406,4406, 0, 0, 146, 146,0.000000 }, - {4406,4406, 73, 0, 886, 886,0.000000 }, - {4407,4407, 0, 0, 40, 0,0.000000 }, - {4408,4408, 0, 0, 486, 0,0.000000 }, - {4409,4409, 0, 0, 1226, 1226,0.000000 }, - {4410,4410, 0, 0, 1480, 1480,0.000000 }, - {4411,4411, 0, 0, 46, 46,0.000000 }, - {4412,4412, 0, 0, 126, 126,0.000000 }, - {4412,4412, 12, 0, 106, 106,0.000000 }, - {4413,4413, 0, 0, 160, 160,0.000000 }, - {4413,4413, 1, 0, 153, 153,0.000000 }, - {4414,4414, 0, 0, 20, 20,0.000000 }, - {4414,4414, 23, 0, 26, 26,0.000000 }, - {4415,4415, 0, 0, 140, 140,0.000000 }, - {4416,4416, 0, 0, 486, 486,0.000000 }, - {4417,4417, 0, 0, 40000, 13,0.000000 }, - {4418,4418, 0, 0, 40000, 0,0.000000 }, - {4419,4419, 0, 0, 1226, 1226,0.000000 }, - {4420,4420, 0, 0, 766, 766,0.000000 }, - {4421,4421, 0, 0, 93, 93,0.000000 }, - {4422,4422, 0, 2, 40000, 0,0.000000 }, + { 0, 0, 0, 0, 9006, 133,0 }, + { 1, 1, 0, 0, 9206, 146,0 }, + { 2, 2, 0, 0, 9246, 240,0 }, + { 3, 3, 0, 0, 9440, 140,0 }, + { 4, 4, 0, 0, 8900, 120,0 }, + { 5, 5, 0, 0, 9400, 140,0 }, + { 6, 6, 0, 0, 7460, 380,0 }, + { 7, 7, 0, 0, 9226, 93,0 }, + { 8, 8, 0, 0, 4613, 420,0 }, + { 9, 9, 0, 0, 7286, 4713,0 }, + { 10, 10, 0, 0, 2280, 746,0 }, + { 11, 11, 0, 0, 9233, 240,0 }, + { 12, 12, 0, 0, 346, 153,0 }, + { 13, 13, 0, 0, 633, 233,0 }, + { 14, 14, 0, 0, 4660, 1573,0 }, + { 15, 15, 0, 0, 1166, 400,0 }, + { 16, 16, 0, 0, 40000, 126,0 }, + { 17, 17, 0, 0, 40000, 93,0 }, + { 18, 18, 0, 0, 40000, 93,0 }, + { 19, 19, 0, 0, 40000, 553,0 }, + { 20, 20, 0, 0, 40000, 660,0 }, + { 21, 21, 0, 0, 40000, 73,0 }, + { 22, 22, 0, 0, 40000, 146,0 }, + { 23, 23, 0, 0, 40000, 146,0 }, + { 24, 24, 0, 0, 4026, 100,0 }, + { 25, 25, 0, 0, 14286, 120,0 }, + { 26, 26, 0, 0, 9233, 106,0 }, + { 27, 27, 0, 0, 4480, 100,0 }, + { 28, 28, 0, 0, 40000, 60,0 }, + { 29, 29, 0, 0, 40000, 80,0 }, + { 30, 30, 0, 0, 40000, 80,0 }, + { 31, 31, 0, 0, 18226, 100,0 }, + { 32, 32, 0, 0, 40000, 0,0 }, + { 33, 33, 0, 0, 40000, 80,0 }, + { 34, 34, 0, 0, 40000, 0,0 }, + { 35, 35, 0, 0, 40000, 53,0 }, + { 36, 36, 0, 0, 40000, 0,0 }, + { 37, 37, 0, 0, 40000, 0,0 }, + { 38, 38, 0, 0, 40000, 0,0 }, + { 39, 39, 0, 0, 40000, 160,0 }, + { 40, 40, 0, 0, 40000, 233,0 }, + { 41, 41, 0, 0, 40000, 73,0 }, + { 42, 42, 0, 0, 40000, 233,0 }, + { 43, 43, 0, 0, 40000, 213,0 }, + { 44, 44, 0, 0, 1246, 453,0 }, + { 45, 45, 0, 0, 4580, 786,0 }, + { 46, 46, 0, 0, 6873, 1246,0 }, + { 47, 47, 0, 0, 40000, 100,0 }, + { 48, 48, 0, 0, 40000, 140,0 }, + { 49, 49, 0, 0, 40000, 393,0 }, + { 50, 50, 0, 0, 40000, 406,0 }, + { 51, 51, 0, 0, 40000, 373,0 }, + { 52, 52, 0, 0, 40000, 0,0 }, + { 53, 53, 0, 0, 40000, 360,0 }, + { 54, 54, 0, 0, 1060, 380,0 }, + { 55, 55, 0, 0, 40000, 80,0 }, + { 56, 56, 0, 0, 40000, 73,0 }, + { 57, 57, 0, 0, 40000, 66,0 }, + { 58, 58, 0, 0, 40000, 60,0 }, + { 59, 59, 0, 0, 40000, 73,0 }, + { 60, 60, 0, 0, 40000, 66,0 }, + { 61, 61, 0, 0, 40000, 86,0 }, + { 62, 62, 0, 0, 40000, 66,0 }, + { 63, 63, 0, 0, 40000, 73,0 }, + { 64, 64, 0, 0, 40000, 80,0 }, + { 65, 65, 0, 0, 40000, 80,0 }, + { 66, 66, 0, 0, 40000, 73,0 }, + { 67, 67, 0, 0, 40000, 73,0 }, + { 68, 68, 0, 0, 40000, 53,0 }, + { 69, 69, 0, 0, 40000, 73,0 }, + { 70, 70, 0, 0, 40000, 126,0 }, + { 71, 71, 0, 0, 40000, 73,0 }, + { 72, 72, 0, 0, 40000, 73,0 }, + { 73, 73, 0, 0, 40000, 73,0 }, + { 74, 74, 0, 0, 40000, 66,0 }, + { 75, 75, 0, 0, 40000, 153,0 }, + { 76, 76, 0, 0, 40000, 153,0 }, + { 77, 77, 0, 0, 40000, 146,0 }, + { 78, 78, 0, 0, 40000, 146,0 }, + { 79, 79, 0, 0, 40000, 66,0 }, + { 80, 80, 0, 0, 40000, 60,0 }, + { 81, 81, 0, 0, 40000, 86,0 }, + { 82, 82, 0, 0, 40000, 73,0 }, + { 83, 83, 0, 0, 40000, 66,0 }, + { 84, 84, 0, 0, 40000, 153,0 }, + { 85, 85, 0, 0, 40000, 233,0 }, + { 86, 86, 0, 0, 40000, 80,0 }, + { 87, 87, 0, 0, 40000, 400,0 }, + { 88, 88, 0, 0, 40000, 1373,0 }, + { 89, 89, 0, 0, 40000, 193,0 }, + { 90, 90, 0, 0, 40000, 1273,0 }, + { 91, 91, 0, 0, 40000, 186,0 }, + { 92, 92, 0, 0, 40000, 86,0 }, + { 93, 93, 0, 0, 40000, 286,0 }, + { 94, 94, 0, 0, 40000, 140,0 }, + { 95, 95, 0, 0, 7440, 2473,0 }, + { 96, 96, 0, 0, 40000, 1220,0 }, + { 97, 97, 0, 0, 4946, 2713,0 }, + { 98, 98, 0, 0, 40000, 160,0 }, + { 99, 99, 0, 0, 8966, 406,0 }, + { 100, 100, 0, 0, 40000, 1353,0 }, + { 101, 101, 0, 0, 40000, 1306,0 }, + { 102, 102, 0, 0, 40000, 933,0 }, + { 103, 103, 0, 0, 9086, 226,0 }, + { 104, 104, 0, 0, 7233, 326,0 }, + { 105, 105, 0, 0, 7286, 200,0 }, + { 106, 106, 0, 0, 14180, 4406,0 }, + { 107, 107, 0, 0, 1180, 406,0 }, + { 108, 108, 0, 0, 40000, 66,0 }, + { 109, 109, 0, 0, 40000, 213,0 }, + { 110, 110, 0, 0, 40000, 73,0 }, + { 111, 111, 0, 0, 4606, 413,0 }, + { 112, 112, 0, 0, 613, 240,0 }, + { 113, 113, 0, 0, 1166, 400,0 }, + { 114, 114, 0, 0, 200, 353,0 }, + { 115, 115, 0, 0, 4553, 1480,0 }, + { 116, 116, 0, 0, 3740, 1260,0 }, + { 117, 117, 0, 0, 7240, 2300,0 }, + { 118, 118, 0, 0, 3020, 73,0 }, + { 119, 119, 0, 0, 1626, 800,0 }, + { 120, 120, 0, 0, 2466, 620,0 }, + { 121, 121, 0, 0, 12053, 3160,0 }, + { 122, 122, 0, 0, 466, 120,0 }, + { 123, 123, 0, 0, 1000, 320,0 }, + { 124, 124, 0, 0, 380, 60,0 }, + { 125, 125, 0, 0, 40000, 200,0 }, + { 126, 126, 0, 0, 560, 86,0 }, + { 127, 127, 35, 0, 386, 160,0 }, + { 128, 128, 52, 0, 126, 26,0 }, + { 129, 129, 48, 0, 286, 126,0 }, + { 130, 130, 58, 0, 173, 93,0 }, + { 129, 129, 60, 0, 286, 126,0 }, + { 131, 131, 47, 0, 520, 200,0 }, + { 132, 132, 43, 0, 173, 93,0 }, + { 131, 131, 49, 0, 520, 200,0 }, + { 133, 133, 43, 0, 160, 80,0 }, + { 131, 131, 51, 0, 526, 206,0 }, + { 134, 134, 43, 0, 1860, 653,0 }, + { 131, 131, 54, 0, 520, 200,0 }, + { 131, 131, 57, 0, 520, 200,0 }, + { 135, 135, 72, 0, 1860, 633,0 }, + { 131, 131, 60, 0, 506, 200,0 }, + { 136, 136, 76, 0, 1566, 546,0 }, + { 137, 137, 84, 0, 1340, 466,0 }, + { 138, 138, 36, 0, 1220, 433,0 }, + { 139, 139, 65, 0, 293, 133,0 }, + { 140, 140, 84, 0, 1333, 460,0 }, + { 141, 141, 83, 0, 220, 113,0 }, + { 135, 135, 84, 0, 1366, 473,0 }, + { 142, 142, 24, 0, 1893, 633,0 }, + { 136, 136, 77, 0, 1586, 553,0 }, + { 143, 143, 60, 0, 173, 93,0 }, + { 144, 144, 65, 0, 213, 126,0 }, + { 145, 145, 59, 0, 173, 0,0 }, + { 146, 146, 51, 0, 173, 100,0 }, + { 147, 147, 45, 0, 260, 206,0 }, + { 148, 148, 71, 0, 433, 180,0 }, + { 149, 149, 60, 0, 280, 26,0 }, + { 150, 150, 58, 0, 500, 186,0 }, + { 151, 151, 53, 0, 513, 200,0 }, + { 152, 152, 64, 0, 220, 86,0 }, + { 153, 153, 71, 0, 106, 46,0 }, + { 154, 154, 61, 0, 993, 340,0 }, + { 155, 155, 61, 0, 1906, 640,0 }, + { 156, 156, 44, 0, 206, 86,0 }, + { 157, 157, 40, 0, 586, 140,0 }, + { 158, 158, 69, 0, 126, 140,0 }, + { 159, 159, 68, 0, 126, 140,0 }, + { 160, 160, 63, 0, 146, 166,0 }, + { 161, 161, 74, 0, 280, 100,0 }, + { 162, 162, 60, 0, 1026, 320,0 }, + { 163, 163, 80, 0, 226, 100,0 }, + { 164, 164, 64, 0, 2713, 913,0 }, + { 165, 165, 72, 0, 120, 66,0 }, + { 166, 166, 73, 0, 386, 80,0 }, + { 167, 167, 70, 0, 553, 306,0 }, + { 168, 168, 68, 0, 126, 140,0 }, + { 169, 169, 48, 0, 386, 373,0 }, + { 131, 131, 53, 0, 520, 206,0 }, + { 170, 170, 0, 0, 40000, 0,0 }, + { 171, 171, 0, 0, 40000, 73,0 }, + { 172, 173, 0, 4, 5886, 100,0 }, + { 174, 175, 0, 4, 6913, 0,0 }, + { 176, 177, 0, 4, 4873, 0,0 }, + { 178, 178, 0, 0, 40000, 0,0 }, + { 179, 180, 0, 4, 4653, 433,0 }, + { 181, 181, 0, 0, 2280, 746,0 }, + { 182, 182, 0, 0, 40000, 0,0 }, + { 183, 184, 0, 4, 626, 0,0 }, + { 185, 186, 0, 4, 4653, 1546,0 }, + { 187, 187, 0, 0, 1166, 400,0 }, + { 188, 189, 0, 4, 40000, 60,0 }, + { 190, 191, 0, 4, 40000, 60,0 }, + { 192, 193, 0, 4, 40000, 73,0 }, + { 194, 194, 0, 0, 40000, 73,0 }, + { 195, 196, 0, 4, 40000, 66,0 }, + { 197, 198, 0, 4, 40000, 86,0 }, + { 199, 200, 0, 4, 40000, 66,0 }, + { 201, 202, 0, 4, 3713, 100,0 }, + { 203, 204, 0, 4, 14753, 126,0 }, + { 205, 206, 0, 4, 9286, 146,0 }, + { 207, 208, 0, 4, 14713, 126,0 }, + { 209, 210, 0, 4, 4653, 0,0 }, + { 211, 212, 0, 4, 40000, 66,0 }, + { 213, 213, 0, 0, 40000, 73,0 }, + { 214, 215, 0, 4, 626, 0,0 }, + { 216, 217, 0, 4, 4066, 100,0 }, + { 218, 219, 0, 4, 14586, 193,0 }, + { 220, 221, 0, 4, 2813, 106,0 }, + { 222, 223, 0, 4, 500, 0,0 }, + { 224, 224, 0, 0, 40000, 0,0 }, + { 225, 226, 0, 4, 7993, 93,0 }, + { 227, 227, 0, 0, 40000, 0,0 }, + { 228, 228, 0, 0, 40000, 133,0 }, + { 229, 230, 0, 4, 720, 213,0 }, + { 231, 232, 0, 4, 40000, 146,0 }, + { 233, 234, 0, 4, 40000, 0,0 }, + { 235, 236, 0, 4, 1000, 340,0 }, + { 235, 237, 0, 4, 3280, 1120,0 }, + { 46, 238, 0, 4, 6920, 0,0 }, + { 239, 240, 0, 4, 40000, 140,0 }, + { 241, 242, 0, 4, 40000, 146,0 }, + { 243, 243, 0, 0, 40000, 100,0 }, + { 244, 244, 0, 0, 40000, 60,0 }, + { 245, 245, 0, 0, 40000, 73,0 }, + { 246, 247, 0, 4, 720, 106,0 }, + { 248, 249, 0, 4, 40000, 126,0 }, + { 250, 250, 0, 0, 40000, 0,0 }, + { 251, 251, 0, 0, 40000, 126,0 }, + { 252, 253, 0, 4, 40000, 66,0 }, + { 254, 255, 0, 4, 40000, 93,0 }, + { 256, 257, 0, 4, 40000, 73,0 }, + { 258, 259, 0, 4, 40000, 86,0 }, + { 260, 261, 0, 4, 40000, 93,0 }, + { 262, 263, 0, 4, 40000, 80,0 }, + { 264, 265, 0, 4, 40000, 200,0 }, + { 266, 267, 0, 4, 40000, 73,0 }, + { 268, 269, 0, 4, 40000, 80,0 }, + { 270, 271, 0, 4, 40000, 73,0 }, + { 272, 273, 0, 4, 40000, 126,0 }, + { 274, 275, 0, 4, 40000, 100,0 }, + { 276, 276, 0, 0, 40000, 113,0 }, + { 277, 278, 0, 4, 40000, 186,0 }, + { 279, 280, 0, 4, 40000, 160,0 }, + { 281, 282, 0, 4, 40000, 206,0 }, + { 283, 283, 0, 0, 40000, 80,0 }, + { 284, 285, 0, 4, 40000, 73,0 }, + { 286, 287, 0, 4, 40000, 73,0 }, + { 288, 288, 0, 0, 40000, 93,0 }, + { 289, 290, 0, 4, 40000, 66,0 }, + { 291, 292, 0, 4, 40000, 153,0 }, + { 293, 294, 0, 4, 40000, 153,0 }, + { 295, 296, 0, 4, 40000, 320,0 }, + { 88, 297, 0, 4, 40000, 1280,0 }, + { 298, 299, 0, 4, 40000, 266,0 }, + { 300, 301, 0, 4, 40000, 1180,0 }, + { 302, 302, 0, 0, 40000, 286,0 }, + { 303, 303, 0, 0, 40000, 140,0 }, + { 304, 304, 0, 0, 13246, 2473,0 }, + { 305, 306, 0, 4, 40000, 1073,0 }, + { 307, 307, 0, 0, 9233, 240,0 }, + { 308, 308, 0, 0, 1186, 406,0 }, + { 309, 309, 0, 0, 40000, 1306,0 }, + { 310, 310, 0, 0, 40000, 933,0 }, + { 311, 312, 0, 4, 9146, 240,0 }, + { 313, 314, 0, 4, 7306, 326,0 }, + { 315, 316, 0, 4, 3586, 326,0 }, + { 317, 318, 0, 4, 7180, 0,0 }, + { 107, 319, 0, 4, 1180, 406,0 }, + { 108, 320, 0, 4, 40000, 66,0 }, + { 109, 321, 0, 4, 720, 213,0 }, + { 322, 323, 0, 4, 40000, 73,0 }, + { 324, 325, 0, 4, 613, 246,0 }, + { 326, 327, 0, 4, 1213, 386,0 }, + { 328, 328, 0, 0, 173, 106,0 }, + { 329, 329, 0, 0, 966, 333,0 }, + { 330, 331, 0, 4, 1906, 320,0 }, + { 332, 332, 0, 0, 3120, 73,0 }, + { 333, 333, 0, 0, 226, 73,0 }, + { 334, 334, 0, 0, 6600, 806,0 }, + { 335, 335, 0, 0, 273, 60,0 }, + { 336, 336, 0, 0, 12053, 660,0 }, + { 337, 337, 0, 0, 40000, 240,0 }, + { 338, 339, 0, 6, 6, 0,0 }, + { 340, 341, 0, 4, 560, 0,0 }, + { 342, 342, 35, 0, 40000, 0,0 }, + { 343, 343, 0, 0, 180, 100,0 }, + { 344, 344, 35, 0, 340, 146,0 }, + { 345, 345, 35, 0, 213, 33,0 }, + { 346, 346, 50, 0, 306, 20,0 }, + { 347, 347, 18, 0, 420, 146,0 }, + { 348, 348, 72, 0, 173, 86,0 }, + { 349, 349, 74, 0, 160, 93,0 }, + { 350, 350, 35, 0, 380, 146,0 }, + { 351, 351, 16, 0, 1206, 420,0 }, + { 352, 352, 0, 2, 6, 0,0 }, + { 353, 353, 38, 0, 200, 106,0 }, + { 354, 354, 38, 0, 346, 146,0 }, + { 355, 355, 31, 0, 406, 20,0 }, + { 355, 355, 35, 0, 406, 66,0 }, + { 355, 355, 38, 0, 406, 66,0 }, + { 355, 355, 41, 0, 406, 66,0 }, + { 355, 355, 45, 0, 306, 73,0 }, + { 355, 355, 50, 0, 306, 73,0 }, + { 356, 356, 36, 0, 1373, 493,0 }, + { 357, 357, 36, 0, 146, 33,0 }, + { 358, 358, 48, 0, 213, 86,0 }, + { 358, 358, 36, 0, 246, 86,0 }, + { 359, 359, 36, 0, 113, 0,0 }, + { 360, 360, 0, 0, 133, 40,0 }, + { 361, 361, 61, 0, 180, 26,0 }, + { 362, 362, 96, 0, 706, 266,0 }, + { 363, 363, 38, 0, 520, 193,0 }, + { 127, 127, 16, 0, 620, 233,0 }, + { 364, 365, 18, 4, 200, 0,0 }, + { 366, 366, 30, 0, 406, 246,0 }, + { 367, 368, 35, 4, 200, 0,0 }, + { 129, 129, 0, 0, 353, 153,0 }, + { 369, 369, 0, 0, 213, 13,0 }, + { 370, 370, 88, 0, 333, 113,0 }, + { 371, 371, 88, 0, 140, 73,0 }, + { 372, 372, 79, 0, 2540, 1040,0 }, + { 135, 135, 14, 0, 9213, 3066,0 }, + { 373, 373, 46, 0, 1093, 60,0 }, + { 374, 375,129, 4, 1200, 433,0 }, + { 376, 376, 58, 0, 1600, 726,0 }, + { 377, 377,164, 0, 526, 820,0 }, + { 378, 378,142, 0, 9153, 3073,0 }, + { 379, 379, 9, 0, 200, 100,0 }, + { 380, 381, 35, 4, 2353, 813,0 }, + { 382, 382, 28, 0, 1060, 120,0 }, + { 383, 383, 46, 0, 953, 20,0 }, + { 384, 384, 60, 0, 440, 160,0 }, + { 384, 384, 54, 0, 513, 180,0 }, + { 385, 385, 72, 0, 253, 120,0 }, + { 385, 385, 67, 0, 253, 113,0 }, + { 385, 385, 60, 0, 253, 106,0 }, + { 386, 386, 1, 0, 966, 613,0 }, + { 387, 387, 77, 0, 340, 86,0 }, + { 387, 387, 72, 0, 340, 86,0 }, + { 388, 388, 90, 0, 213, 86,0 }, + { 389, 389, 39, 0, 266, 73,0 }, + { 390, 390, 36, 0, 593, 73,0 }, + { 391, 392, 35, 4, 173, 46,0 }, + { 391, 393, 35, 4, 460, 66,0 }, + { 394, 394, 60, 0, 173, 20,0 }, + { 328, 328, 7, 0, 173, 0,0 }, + { 395, 395, 90, 0, 193, 20,0 }, + { 396, 396, 90, 0, 793, 40,0 }, + { 397, 397, 35, 0, 253, 86,0 }, + { 398, 399, 5, 4, 1913, 226,0 }, + { 400, 400,103, 0, 713, 273,0 }, + { 401, 401, 3, 0, 100, 0,0 }, + { 169, 169, 1, 0, 466, 413,0 }, + { 131, 131, 0, 0, 613, 226,0 }, + { 402, 402, 36, 0, 273, 53,0 }, + { 403, 403, 60, 0, 40000, 73,0 }, + { 404, 404, 37, 0, 1193, 426,0 }, + { 405, 405, 36, 0, 406, 20,0 }, + { 406, 406, 32, 0, 146, 73,0 }, + { 407, 407, 50, 0, 40000, 0,0 }, + { 408, 408, 50, 0, 793, 346,0 }, + { 409, 409, 83, 0, 120, 13,0 }, + { 410, 410, 72, 0, 433, 0,0 }, + { 148, 148, 59, 0, 513, 200,0 }, + { 411, 411, 64, 0, 173, 93,0 }, + { 411, 411, 60, 0, 173, 93,0 }, + { 412, 412, 72, 0, 160, 93,0 }, + { 412, 412, 62, 0, 173, 93,0 }, + { 413, 413, 83, 0, 773, 60,0 }, + { 414, 414, 0, 0, 40000, 80,0 }, + { 415, 415, 0, 0, 40000, 0,0 }, + { 416, 416, 0, 0, 40000, 73,0 }, + { 417, 417, 0, 0, 40000, 86,0 }, + { 418, 418, 0, 0, 40000, 0,0 }, + { 419, 419, 0, 0, 3440, 100,0 }, + { 420, 420, 0, 0, 3913, 420,0 }, + { 421, 421, 0, 0, 13620, 4640,0 }, + { 422, 422, 0, 0, 9233, 240,0 }, + { 423, 423, 0, 0, 633, 233,0 }, + { 424, 424, 0, 0, 4660, 1573,0 }, + { 425, 425, 0, 0, 4480, 1413,0 }, + { 426, 426, 0, 0, 40000, 0,0 }, + { 427, 427, 0, 0, 40000, 86,0 }, + { 428, 428, 60, 2, 6, 0,0 }, + { 429, 429, 73, 0, 593, 86,0 }, + { 429, 429, 74, 0, 593, 86,0 }, + { 429, 429, 80, 0, 593, 86,0 }, + { 429, 429, 84, 0, 593, 86,0 }, + { 429, 429, 92, 0, 520, 86,0 }, + { 430, 430, 81, 0, 786, 80,0 }, + { 430, 430, 83, 0, 786, 80,0 }, + { 430, 430, 95, 0, 680, 80,0 }, + { 431, 431, 35, 0, 593, 140,0 }, + { 432, 432, 60, 0, 213, 133,0 }, + { 357, 357, 59, 0, 113, 0,0 }, + { 432, 432, 44, 0, 213, 133,0 }, + { 433, 433, 41, 0, 713, 273,0 }, + { 434, 434, 97, 0, 113, 46,0 }, + { 433, 433, 44, 0, 513, 206,0 }, + { 433, 433, 48, 0, 506, 200,0 }, + { 435, 435, 96, 0, 700, 86,0 }, + { 433, 433, 51, 0, 520, 200,0 }, + { 433, 433, 54, 0, 513, 206,0 }, + { 436, 436, 40, 0, 1506, 793,0 }, + { 433, 433, 57, 0, 380, 160,0 }, + { 437, 437, 58, 0, 1600, 726,0 }, + { 438, 438, 97, 0, 233, 106,0 }, + { 439, 439, 50, 0, 186, 93,0 }, + { 437, 437, 60, 0, 1573, 713,0 }, + { 440, 440, 53, 0, 180, 73,0 }, + { 441, 441, 46, 0, 173, 126,0 }, + { 440, 440, 57, 0, 180, 40,0 }, + { 442, 442, 42, 0, 640, 240,0 }, + { 442, 442, 37, 0, 633, 233,0 }, + { 443, 443, 41, 0, 626, 240,0 }, + { 443, 443, 37, 0, 620, 233,0 }, + { 444, 444, 77, 0, 173, 40,0 }, + { 444, 444, 72, 0, 173, 40,0 }, + { 445, 445, 70, 0, 233, 100,0 }, + { 445, 445, 90, 0, 233, 93,0 }, + { 446, 446, 46, 0, 133, 73,0 }, + { 447, 447, 48, 0, 333, 73,0 }, + { 448, 448, 85, 0, 106, 0,0 }, + { 449, 449, 66, 0, 180, 26,0 }, + { 449, 449, 61, 0, 180, 26,0 }, + { 450, 450, 41, 0, 200, 66,0 }, + { 451, 451, 41, 0, 253, 66,0 }, + { 452, 452, 81, 0, 253, 26,0 }, + { 400, 400, 81, 0, 820, 306,0 }, + { 400, 400, 76, 0, 813, 300,0 }, + { 359, 359, 60, 0, 100, 0,0 }, + { 453, 453, 53, 0, 40000, 0,0 }, + { 454, 454, 0, 2, 6, 0,0 }, + { 455, 455, 0, 0, 200, 20,0 }, + { 456, 456, 0, 0, 4480, 100,0 }, + { 457, 457, 0, 0, 1180, 406,0 }, + { 458, 458, 0, 0, 40000, 86,0 }, + { 459, 459, 0, 0, 40000, 73,0 }, + { 460, 460, 0, 0, 3700, 66,0 }, + { 461, 461, 0, 0, 40000, 0,0 }, + { 462, 462, 0, 0, 6746, 2606,0 }, + { 463, 463, 0, 0, 40000, 213,0 }, + { 464, 464, 0, 0, 40000, 66,0 }, + { 465, 465, 0, 0, 40000, 100,0 }, + { 466, 466, 0, 0, 40000, 100,0 }, + { 467, 467, 0, 0, 5840, 806,0 }, + { 468, 468, 0, 0, 40000, 0,0 }, + { 469, 469, 0, 0, 40000, 0,0 }, + { 470, 470, 0, 0, 40000, 73,0 }, + { 471, 471, 0, 0, 40000, 133,0 }, + { 472, 472, 0, 0, 3320, 800,0 }, + { 473, 473, 0, 0, 40000, 173,0 }, + { 474, 474, 0, 0, 40000, 193,0 }, + { 475, 475, 0, 0, 2373, 800,0 }, + { 476, 476, 0, 0, 40000, 4986,0 }, + { 477, 477, 0, 0, 1180, 413,0 }, + { 478, 478, 0, 0, 3673, 1200,0 }, + { 479, 479, 0, 0, 973, 800,0 }, + { 480, 480, 0, 0, 7233, 2286,0 }, + { 481, 481, 0, 0, 40000, 73,0 }, + { 482, 482, 0, 0, 2526, 73,0 }, + { 483, 483, 0, 0, 393, 126,0 }, + { 484, 484, 0, 0, 40000, 200,0 }, + { 485, 485, 0, 0, 40000, 546,0 }, + { 486, 486, 0, 0, 1186, 413,0 }, + { 487, 487, 0, 0, 14166, 320,0 }, + { 488, 488, 0, 0, 8326, 646,0 }, + { 489, 489, 0, 0, 513, 206,0 }, + { 490, 490, 0, 0, 40000, 93,0 }, + { 491, 491, 50, 0, 1406, 353,0 }, + { 492, 492, 37, 0, 1040, 400,0 }, + { 493, 493, 39, 0, 406, 73,0 }, + { 494, 494, 39, 0, 3746, 860,0 }, + { 495, 495, 86, 0, 2133, 173,0 }, + { 496, 496, 43, 0, 140, 66,0 }, + { 127, 127, 24, 0, 513, 206,0 }, + { 127, 127, 29, 0, 520, 206,0 }, + { 497, 497, 50, 0, 340, 20,0 }, + { 498, 498, 30, 0, 5306, 1266,0 }, + { 498, 498, 33, 0, 3773, 886,0 }, + { 498, 498, 38, 0, 3746, 860,0 }, + { 498, 498, 42, 0, 3793, 906,0 }, + { 499, 499, 24, 0, 266, 0,0 }, + { 499, 499, 27, 0, 260, 153,0 }, + { 499, 499, 29, 0, 260, 153,0 }, + { 499, 499, 32, 0, 260, 153,0 }, + { 500, 500, 32, 0, 106, 0,0 }, + { 501, 501, 53, 0, 373, 186,0 }, + { 501, 501, 57, 0, 380, 193,0 }, + { 502, 502, 60, 0, 286, 133,0 }, + { 503, 503, 55, 0, 460, 126,0 }, + { 486, 486, 85, 0, 813, 293,0 }, + { 504, 504, 90, 0, 1580, 546,0 }, + { 505, 505, 84, 0, 246, 120,0 }, + { 506, 506, 48, 0, 826, 646,0 }, + { 507, 507, 48, 0, 266, 213,0 }, + { 132, 132, 72, 0, 126, 66,0 }, + { 508, 508, 72, 0, 106, 0,0 }, + { 509, 509, 72, 0, 100, 0,0 }, + { 510, 510, 63, 0, 1860, 633,0 }, + { 510, 510, 65, 0, 1853, 633,0 }, + { 511, 511, 79, 0, 1573, 553,0 }, + { 512, 512, 38, 0, 520, 793,0 }, + { 513, 513, 94, 0, 380, 160,0 }, + { 514, 514, 87, 0, 433, 306,0 }, + { 514, 514, 94, 0, 380, 273,0 }, + { 515, 515, 80, 0, 546, 273,0 }, + { 516, 516, 47, 0, 506, 200,0 }, + { 517, 517, 61, 0, 286, 133,0 }, + { 517, 517, 68, 0, 246, 120,0 }, + { 518, 518, 61, 0, 513, 206,0 }, + { 518, 518, 68, 0, 433, 180,0 }, + { 499, 499, 60, 0, 220, 133,0 }, + { 519, 519, 60, 0, 153, 46,0 }, + { 520, 520, 36, 0, 200, 20,0 }, + { 520, 520, 60, 0, 173, 20,0 }, + { 521, 521, 60, 0, 173, 20,0 }, + { 522, 522, 68, 0, 126, 26,0 }, + { 523, 523, 71, 0, 160, 186,0 }, + { 523, 523, 72, 0, 160, 186,0 }, + { 524, 524,101, 0, 966, 353,0 }, + { 525, 525, 36, 0, 3333, 480,0 }, + { 526, 526, 25, 0, 40000, 2293,0 }, + { 527, 527, 37, 0, 2106, 426,0 }, + { 528, 528, 36, 0, 720, 266,0 }, + { 528, 528, 41, 0, 713, 266,0 }, + { 529, 529, 84, 0, 173, 60,0 }, + { 530, 530, 54, 0, 40000, 0,0 }, + { 481, 481, 48, 0, 40000, 73,0 }, + { 531, 531, 0, 0, 10060, 1266,0 }, + { 532, 532, 0, 0, 4600, 606,0 }, + { 533, 533, 0, 0, 40000, 253,0 }, + { 534, 534, 0, 0, 40000, 73,0 }, + { 535, 535, 0, 0, 40000, 66,0 }, + { 536, 536, 0, 0, 40000, 80,0 }, + { 537, 537, 0, 0, 9413, 1393,0 }, + { 538, 538, 0, 0, 9000, 66,0 }, + { 539, 539, 0, 0, 40000, 0,0 }, + { 540, 540, 0, 0, 40000, 80,0 }, + { 541, 541, 0, 0, 40000, 120,0 }, + { 542, 542, 0, 0, 253, 73,0 }, + { 543, 543, 0, 0, 40000, 73,0 }, + { 544, 544, 0, 0, 18280, 800,0 }, + { 545, 545, 0, 0, 40000, 1133,0 }, + { 546, 546, 0, 0, 40000, 1226,0 }, + { 547, 547, 0, 0, 40000, 153,0 }, + { 135, 135, 49, 0, 3633, 1186,0 }, + { 548, 548, 35, 0, 2193, 80,0 }, + { 549, 549, 41, 0, 73, 0,0 }, + { 366, 366, 38, 0, 406, 246,0 }, + { 550, 550, 39, 0, 106, 20,0 }, + { 551, 551, 49, 0, 200, 133,0 }, + { 408, 408, 59, 0, 780, 326,0 }, + { 552, 552, 24, 0, 40000, 0,0 }, + { 552, 552, 27, 0, 40000, 0,0 }, + { 552, 552, 29, 0, 40000, 0,0 }, + { 552, 552, 32, 0, 40000, 0,0 }, + { 553, 553, 84, 0, 200, 33,0 }, + { 512, 512, 79, 0, 346, 460,0 }, + { 554, 554, 61, 0, 400, 126,0 }, + { 554, 554, 68, 0, 353, 120,0 }, + { 555, 555, 36, 0, 146, 86,0 }, + { 555, 555, 60, 0, 113, 0,0 }, + { 556, 556, 36, 0, 273, 53,0 }, + { 115, 115, 37, 0, 4580, 1513,0 }, + { 557, 557, 0, 0, 3806, 73,0 }, + { 558, 558, 0, 0, 40000, 0,0 }, + { 559, 559, 0, 0, 40000, 66,0 }, + { 560, 560, 0, 0, 5886, 133,0 }, + { 561, 561, 0, 0, 253, 26,0 }, + { 562, 562, 0, 0, 3246, 753,0 }, + { 563, 563, 0, 0, 40000, 100,0 }, + { 564, 564, 0, 0, 1620, 366,0 }, + { 565, 565, 0, 0, 40000, 0,0 }, + { 566, 566, 0, 0, 40000, 0,0 }, + { 567, 567, 0, 0, 40000, 0,0 }, + { 568, 568, 0, 0, 40000, 80,0 }, + { 569, 569, 0, 0, 760, 340,0 }, + { 570, 570, 0, 0, 40000, 0,0 }, + { 571, 571, 0, 0, 40000, 0,0 }, + { 572, 572, 0, 0, 40000, 0,0 }, + { 356, 356, 0, 0, 1893, 646,0 }, + { 573, 573, 0, 0, 40000, 93,0 }, + { 574, 574, 0, 0, 40000, 93,0 }, + { 575, 575, 0, 0, 40000, 200,0 }, + { 576, 576, 0, 0, 40000, 200,0 }, + { 577, 577, 0, 0, 40000, 126,0 }, + { 578, 578, 0, 0, 40000, 353,0 }, + { 579, 579, 0, 0, 40000, 346,0 }, + { 580, 580, 0, 0, 40000, 353,0 }, + { 581, 581, 0, 0, 40000, 100,0 }, + { 582, 582, 0, 0, 40000, 133,0 }, + { 583, 583, 0, 0, 2286, 713,0 }, + { 584, 584, 0, 0, 40000, 193,0 }, + { 585, 585, 0, 0, 40000, 0,0 }, + { 516, 516, 0, 0, 633, 240,0 }, + { 586, 586, 0, 0, 40000, 73,0 }, + { 587, 587, 0, 0, 40000, 73,0 }, + { 588, 588, 0, 0, 40000, 73,0 }, + { 498, 498, 26, 0, 5293, 1253,0 }, + { 494, 494, 35, 0, 3800, 913,0 }, + { 350, 350, 41, 0, 380, 153,0 }, + { 353, 353, 48, 0, 173, 100,0 }, + { 354, 354, 67, 0, 246, 120,0 }, + { 502, 502, 24, 0, 340, 146,0 }, + { 346, 346, 36, 0, 406, 73,0 }, + { 346, 346, 38, 0, 406, 20,0 }, + { 346, 346, 40, 0, 406, 73,0 }, + { 346, 346, 42, 0, 406, 20,0 }, + { 346, 346, 44, 0, 306, 20,0 }, + { 510, 510, 55, 0, 1866, 646,0 }, + { 346, 346, 46, 0, 306, 20,0 }, + { 136, 136, 80, 0, 1600, 573,0 }, + { 486, 486, 24, 0, 1193, 426,0 }, + { 153, 153, 50, 0, 106, 40,0 }, + { 346, 346, 24, 0, 540, 73,0 }, + { 516, 516, 31, 0, 626, 240,0 }, + { 498, 498, 35, 0, 3760, 880,0 }, + { 517, 517, 60, 0, 286, 133,0 }, + { 530, 530, 36, 0, 40000, 0,0 }, + { 530, 530, 48, 0, 40000, 0,0 }, + { 589, 589, 0, 0, 40000, 0,0 }, + { 139, 139, 76, 0, 253, 106,0 }, + { 156, 156, 48, 0, 206, 80,0 }, + { 157, 157, 48, 0, 426, 106,0 }, + { 165, 165, 69, 0, 120, 66,0 }, + { 167, 167, 75, 0, 546, 306,0 }, + { 590, 590, 0, 0, 40000, 0,0 }, + { 591, 591, 0, 0, 15486, 1580,0 }, + { 592, 592, 0, 0, 3446, 106,0 }, + { 593, 593, 0, 0, 1926, 146,0 }, + { 594, 594, 0, 0, 7293, 2380,0 }, + { 595, 595, 0, 0, 7613, 1566,0 }, + { 596, 596, 0, 0, 1153, 460,0 }, + { 597, 597, 0, 0, 1166, 400,0 }, + { 598, 598, 0, 0, 40000, 73,0 }, + { 599, 599, 0, 0, 40000, 766,0 }, + { 600, 600, 0, 0, 40000, 80,0 }, + { 601, 601, 0, 0, 1840, 513,0 }, + { 602, 602, 0, 0, 40000, 0,0 }, + { 603, 603, 0, 0, 4480, 733,0 }, + { 604, 604, 0, 0, 18226, 786,0 }, + { 605, 605, 0, 0, 4333, 233,0 }, + { 606, 606, 0, 0, 40000, 106,0 }, + { 607, 607, 0, 0, 40000, 366,0 }, + { 608, 608, 0, 0, 40000, 200,0 }, + { 609, 609, 0, 0, 713, 200,0 }, + { 610, 610, 0, 0, 8866, 1366,0 }, + { 611, 611, 0, 0, 2300, 73,0 }, + { 612, 612, 0, 0, 40000, 126,0 }, + { 613, 613, 0, 0, 40000, 1413,0 }, + { 614, 614, 0, 0, 40000, 333,0 }, + { 615, 615, 0, 0, 40000, 333,0 }, + { 616, 616, 0, 0, 40000, 26,0 }, + { 617, 617, 0, 0, 40000, 40,0 }, + { 618, 618, 0, 0, 4240, 353,0 }, + { 619, 619, 0, 0, 40000, 0,0 }, + { 620, 620, 0, 0, 40000, 73,0 }, + { 621, 621, 0, 0, 9020, 60,0 }, + { 622, 622, 0, 0, 3020, 0,0 }, + { 623, 623, 0, 0, 40000, 60,0 }, + { 624, 624, 0, 0, 40000, 73,0 }, + { 625, 625, 0, 0, 40000, 60,0 }, + { 626, 626, 0, 0, 40000, 53,0 }, + { 627, 627, 0, 0, 40000, 0,0 }, + { 628, 628, 0, 0, 40000, 66,0 }, + { 629, 629, 0, 0, 40000, 66,0 }, + { 630, 630, 0, 0, 5913, 426,0 }, + { 631, 631, 0, 0, 40000, 246,0 }, + { 632, 632, 0, 0, 40000, 206,0 }, + { 633, 633, 0, 0, 40000, 0,0 }, + { 634, 634, 0, 0, 2453, 780,0 }, + { 635, 635, 0, 0, 4740, 240,0 }, + { 636, 636, 0, 0, 1840, 353,0 }, + { 637, 637, 0, 0, 40000, 86,0 }, + { 638, 638, 0, 0, 3446, 1786,0 }, + { 346, 346, 0, 0, 540, 20,0 }, + { 639, 639, 0, 0, 7406, 2486,0 }, + { 404, 404, 0, 0, 1220, 466,0 }, + { 506, 506, 0, 0, 1000, 813,0 }, + { 639, 639, 60, 0, 2666, 913,0 }, + { 639, 639, 79, 0, 1366, 486,0 }, + { 640, 640, 65, 0, 2053, 646,0 }, + { 486, 486, 31, 0, 1206, 440,0 }, + { 486, 486, 36, 0, 1200, 433,0 }, + { 640, 640, 72, 0, 1713, 520,0 }, + { 136, 136, 79, 0, 1580, 560,0 }, + { 148, 148, 57, 0, 520, 206,0 }, + { 150, 150, 53, 0, 500, 193,0 }, + { 641, 641, 84, 0, 226, 66,0 }, + { 520, 520, 66, 0, 173, 20,0 }, + { 642, 642, 31, 0, 40000, 113,0 }, + { 642, 642, 29, 0, 40000, 113,0 }, + { 356, 356, 31, 0, 1366, 486,0 }, + { 356, 356, 19, 0, 1866, 633,0 }, + { 643, 643, 31, 0, 40000, 73,0 }, + { 643, 643, 29, 0, 40000, 73,0 }, + { 644, 644, 31, 0, 2286, 400,0 }, + { 644, 644, 35, 0, 2313, 420,0 }, + { 644, 644, 40, 0, 2353, 433,0 }, + { 644, 644, 47, 0, 1860, 346,0 }, + { 516, 516, 32, 0, 626, 240,0 }, + { 516, 516, 43, 0, 506, 200,0 }, + { 495, 495, 26, 0, 3180, 240,0 }, + { 495, 495, 44, 0, 2553, 206,0 }, + { 496, 496, 26, 0, 160, 73,0 }, + { 496, 496, 51, 0, 146, 66,0 }, + { 496, 496, 39, 0, 160, 73,0 }, + { 495, 495, 30, 0, 3180, 240,0 }, + { 645, 645, 44, 0, 1880, 653,0 }, + { 645, 645, 43, 0, 1886, 653,0 }, + { 646, 646, 0, 0, 2393, 833,0 }, + { 647, 647, 0, 0, 4693, 26,0 }, + { 648, 648, 0, 0, 2306, 773,0 }, + { 649, 649, 0, 0, 40000, 120,0 }, + { 650, 650, 0, 0, 40000, 66,0 }, + { 651, 651, 0, 0, 5866, 1206,0 }, + { 652, 652, 0, 0, 40000, 426,0 }, + { 653, 653, 0, 0, 1873, 633,0 }, + { 654, 654, 0, 0, 40000, 66,0 }, + { 655, 655, 0, 0, 40000, 73,0 }, + { 656, 656, 0, 0, 40000, 73,0 }, + { 657, 657, 0, 0, 40000, 0,0 }, + { 658, 658, 0, 0, 2040, 380,0 }, + { 659, 659, 0, 0, 40000, 73,0 }, + { 660, 660, 0, 0, 3720, 1260,0 }, + { 661, 661, 0, 0, 4080, 1046,0 }, + { 662, 662, 0, 0, 8693, 4666,0 }, + { 663, 663, 0, 0, 1926, 73,0 }, + { 664, 664, 0, 0, 8326, 646,0 }, + { 665, 665, 0, 0, 40000, 240,0 }, + { 666, 666, 0, 0, 40000, 226,0 }, + { 667, 667, 0, 0, 40000, 220,0 }, + { 668, 668, 0, 0, 40000, 0,0 }, + { 669, 669, 0, 0, 40000, 193,0 }, + { 670, 670, 0, 0, 880, 20,0 }, + { 671, 671, 0, 0, 4873, 120,0 }, + { 672, 672, 0, 0, 40000, 413,0 }, + { 673, 673, 0, 0, 700, 106,0 }, + { 674, 674, 0, 0, 700, 100,0 }, + { 675, 675, 0, 0, 40000, 126,0 }, + { 676, 676, 0, 0, 8113, 806,0 }, + { 677, 677, 0, 0, 8900, 80,0 }, + { 678, 678, 0, 0, 1893, 653,0 }, + { 679, 679, 0, 0, 3973, 206,0 }, + { 680, 680, 0, 0, 40000, 173,0 }, + { 681, 681, 0, 0, 40000, 73,0 }, + { 682, 682, 0, 0, 40000, 93,0 }, + { 683, 683, 0, 0, 1606, 640,0 }, + { 684, 684, 0, 0, 15486, 1580,0 }, + { 685, 685, 0, 0, 40000, 346,0 }, + { 686, 686, 0, 0, 40000, 786,0 }, + { 687, 687, 0, 0, 386, 240,0 }, + { 688, 688, 0, 0, 40000, 2066,0 }, + { 689, 689, 0, 0, 15453, 73,0 }, + { 690, 690, 0, 0, 1206, 240,0 }, + { 691, 691, 0, 0, 8866, 1366,0 }, + { 692, 692, 0, 0, 5913, 2253,0 }, + { 693, 693, 0, 0, 773, 106,0 }, + { 694, 694, 0, 0, 3793, 73,0 }, + { 695, 695, 0, 0, 40000, 73,0 }, + { 645, 645, 0, 0, 3633, 1180,0 }, + { 696, 696, 0, 0, 40000, 80,0 }, + { 697, 697, 0, 0, 40000, 0,0 }, + { 698, 698, 0, 0, 40000, 66,0 }, + { 699, 699, 0, 0, 40000, 66,0 }, + { 700, 700, 0, 0, 106, 0,0 }, + { 701, 701, 0, 0, 40000, 200,0 }, + { 702, 702, 0, 0, 3913, 73,0 }, + { 703, 703, 0, 0, 40000, 73,0 }, + { 704, 704, 0, 0, 40000, 73,0 }, + { 705, 705, 0, 0, 40000, 73,0 }, + { 706, 706, 0, 0, 40000, 66,0 }, + { 707, 707, 0, 0, 40000, 313,0 }, + { 708, 708, 0, 0, 40000, 100,0 }, + { 709, 709, 0, 0, 40000, 213,0 }, + { 710, 710, 0, 0, 40000, 53,0 }, + { 711, 711, 0, 0, 40000, 40,0 }, + { 712, 712, 0, 0, 40000, 73,0 }, + { 713, 713, 0, 0, 40000, 140,0 }, + { 714, 714, 0, 0, 40000, 606,0 }, + { 715, 715, 0, 0, 40000, 226,0 }, + { 716, 716, 0, 0, 3746, 1273,0 }, + { 717, 717, 0, 0, 40000, 80,0 }, + { 718, 718, 0, 0, 2360, 806,0 }, + { 719, 719, 0, 0, 1186, 420,0 }, + { 720, 720, 0, 0, 12533, 1953,0 }, + { 721, 721, 0, 0, 973, 1280,0 }, + { 722, 722, 0, 0, 40000, 426,0 }, + { 723, 723, 0, 0, 40000, 53,0 }, + { 724, 724, 0, 0, 40000, 66,0 }, + { 725, 725, 0, 0, 1246, 73,0 }, + { 726, 726, 0, 0, 3726, 1246,0 }, + { 727, 727, 0, 0, 2346, 813,0 }, + { 728, 728, 0, 0, 1206, 433,0 }, + { 507, 507, 0, 0, 306, 246,0 }, + { 512, 512, 0, 0, 526, 840,0 }, + { 729, 729, 0, 0, 14793, 4933,0 }, + { 730, 730, 0, 0, 14640, 4806,0 }, + { 731, 731, 0, 0, 5233, 633,0 }, + { 732, 732, 0, 0, 40000, 2513,0 }, + { 733, 733, 0, 0, 40000, 820,0 }, + { 734, 734, 0, 0, 40000, 0,0 }, + { 735, 735, 0, 0, 1726, 793,0 }, + { 736, 736, 0, 0, 513, 20,0 }, + { 737, 737, 0, 2, 6, 0,0 }, + { 738, 738, 38, 0, 1020, 413,0 }, + { 739, 739, 44, 0, 220, 33,0 }, + { 500, 500, 58, 0, 100, 0,0 }, + { 740, 740, 24, 0, 513, 206,0 }, + { 741, 741, 60, 0, 220, 26,0 }, + { 736, 736, 44, 0, 286, 20,0 }, + { 742, 742, 25, 0, 626, 246,0 }, + { 743, 743, 60, 0, 146, 86,0 }, + { 742, 742, 30, 0, 626, 240,0 }, + { 377, 377, 60, 0, 446, 626,0 }, + { 742, 742, 33, 0, 620, 226,0 }, + { 744, 744, 60, 0, 220, 113,0 }, + { 742, 742, 35, 0, 620, 233,0 }, + { 742, 742, 37, 0, 633, 246,0 }, + { 745, 745, 0, 0, 1880, 640,0 }, + { 742, 742, 40, 0, 640, 260,0 }, + { 746, 746,102, 0, 960, 300,0 }, + { 747, 747, 80, 0, 1106, 126,0 }, + { 377, 377, 0, 0, 500, 760,0 }, + { 748, 748, 56, 0, 100, 0,0 }, + { 749, 749, 0, 0, 973, 1300,0 }, + { 746, 746,100, 0, 960, 340,0 }, + { 750, 750, 40, 0, 626, 240,0 }, + { 750, 750, 35, 0, 626, 240,0 }, + { 751, 751, 29, 0, 206, 106,0 }, + { 750, 750, 29, 0, 633, 240,0 }, + { 750, 750, 22, 0, 640, 233,0 }, + { 500, 500, 0, 0, 106, 0,0 }, + { 752, 752, 0, 0, 206, 26,0 }, + { 753, 753, 84, 0, 166, 20,0 }, + { 754, 754, 84, 0, 1580, 553,0 }, + { 755, 755, 0, 0, 633, 233,0 }, + { 755, 755, 71, 0, 440, 180,0 }, + { 755, 755, 53, 0, 513, 200,0 }, + { 755, 755, 48, 0, 520, 206,0 }, + { 756, 756, 95, 0, 286, 20,0 }, + { 757, 757, 95, 0, 1880, 20,0 }, + { 758, 758, 0, 0, 14413, 333,0 }, + { 759, 759, 0, 0, 14453, 360,0 }, + { 760, 760, 0, 0, 14940, 353,0 }, + { 761, 761, 0, 0, 7286, 340,0 }, + { 762, 762, 0, 0, 14700, 60,0 }, + { 763, 763, 0, 0, 14506, 340,0 }, + { 764, 764, 0, 0, 14706, 200,0 }, + { 765, 765, 0, 0, 40000, 0,0 }, + { 766, 766, 0, 0, 2900, 426,0 }, + { 767, 767, 0, 0, 2986, 753,0 }, + { 768, 768, 0, 0, 1706, 680,0 }, + { 769, 769, 0, 0, 14646, 1253,0 }, + { 770, 770, 0, 0, 1713, 486,0 }, + { 771, 771, 0, 0, 966, 346,0 }, + { 772, 772, 0, 0, 3453, 766,0 }, + { 773, 773, 0, 0, 2866, 486,0 }, + { 774, 774, 0, 0, 40000, 73,0 }, + { 775, 775, 0, 0, 40000, 73,0 }, + { 776, 776, 0, 0, 40000, 166,0 }, + { 777, 777, 0, 0, 40000, 126,0 }, + { 778, 778, 0, 0, 40000, 113,0 }, + { 779, 779, 0, 0, 40000, 113,0 }, + { 780, 780, 0, 0, 40000, 93,0 }, + { 781, 781, 0, 0, 40000, 200,0 }, + { 782, 782, 0, 0, 7186, 93,0 }, + { 783, 783, 0, 0, 6406, 120,0 }, + { 784, 784, 0, 0, 40000, 0,0 }, + { 785, 785, 0, 0, 40000, 0,0 }, + { 786, 786, 0, 0, 1220, 73,0 }, + { 787, 787, 0, 0, 40000, 0,0 }, + { 788, 788, 0, 0, 17566, 66,0 }, + { 789, 789, 0, 0, 2333, 26,0 }, + { 790, 790, 0, 0, 4560, 153,0 }, + { 791, 791, 0, 0, 40000, 0,0 }, + { 792, 792, 0, 0, 40000, 0,0 }, + { 793, 793, 0, 0, 40000, 0,0 }, + { 794, 794, 0, 0, 2506, 126,0 }, + { 795, 795, 0, 0, 2513, 126,0 }, + { 796, 796, 0, 0, 40000, 0,0 }, + { 797, 797, 0, 0, 3386, 80,0 }, + { 798, 798, 0, 0, 40000, 100,0 }, + { 799, 799, 0, 0, 40000, 100,0 }, + { 800, 800, 0, 0, 40000, 120,0 }, + { 801, 801, 0, 0, 40000, 0,0 }, + { 802, 802, 0, 0, 40000, 200,0 }, + { 803, 803, 0, 0, 1080, 180,0 }, + { 804, 804, 0, 0, 3620, 1166,0 }, + { 805, 805, 0, 0, 1186, 393,0 }, + { 806, 806, 0, 0, 40000, 213,0 }, + { 807, 807, 0, 0, 40000, 426,0 }, + { 808, 808, 0, 0, 40000, 146,0 }, + { 809, 809, 0, 0, 40000, 146,0 }, + { 810, 810, 0, 0, 40000, 60,0 }, + { 811, 811, 0, 0, 40000, 113,0 }, + { 812, 812, 0, 0, 40000, 93,0 }, + { 813, 813, 0, 0, 1186, 153,0 }, + { 814, 814, 0, 0, 40000, 0,0 }, + { 815, 815, 0, 0, 40000, 80,0 }, + { 816, 816, 0, 0, 40000, 80,0 }, + { 817, 817, 0, 0, 40000, 46,0 }, + { 818, 818, 0, 0, 40000, 0,0 }, + { 819, 819, 0, 0, 40000, 66,0 }, + { 820, 820, 0, 0, 40000, 126,0 }, + { 821, 821, 0, 0, 40000, 213,0 }, + { 822, 822, 0, 0, 40000, 80,0 }, + { 823, 823, 0, 0, 40000, 73,0 }, + { 824, 824, 0, 0, 40000, 73,0 }, + { 825, 825, 0, 0, 40000, 100,0 }, + { 826, 826, 0, 0, 40000, 93,0 }, + { 827, 827, 0, 0, 40000, 73,0 }, + { 828, 828, 0, 0, 40000, 73,0 }, + { 829, 829, 0, 0, 40000, 80,0 }, + { 830, 830, 0, 0, 40000, 80,0 }, + { 831, 831, 0, 0, 40000, 80,0 }, + { 832, 832, 0, 0, 40000, 73,0 }, + { 833, 833, 0, 0, 40000, 80,0 }, + { 834, 834, 0, 0, 40000, 86,0 }, + { 835, 835, 0, 0, 40000, 100,0 }, + { 836, 836, 0, 0, 40000, 100,0 }, + { 837, 837, 0, 0, 40000, 140,0 }, + { 838, 838, 0, 0, 40000, 73,0 }, + { 839, 839, 0, 0, 40000, 0,0 }, + { 840, 840, 0, 0, 40000, 93,0 }, + { 841, 841, 0, 0, 40000, 0,0 }, + { 842, 842, 0, 0, 40000, 0,0 }, + { 843, 843, 0, 0, 40000, 73,0 }, + { 844, 844, 0, 0, 40000, 66,0 }, + { 845, 845, 0, 0, 40000, 0,0 }, + { 846, 846, 0, 0, 40000, 193,0 }, + { 847, 847, 0, 0, 40000, 340,0 }, + { 848, 848, 0, 0, 40000, 233,0 }, + { 849, 849, 0, 0, 40000, 80,0 }, + { 850, 850, 0, 0, 40000, 186,0 }, + { 851, 851, 0, 0, 9973, 426,0 }, + { 852, 852, 0, 0, 40000, 200,0 }, + { 853, 853, 0, 0, 40000, 400,0 }, + { 854, 854, 0, 0, 14633, 200,0 }, + { 855, 855, 0, 0, 40000, 333,0 }, + { 856, 856, 0, 0, 4620, 800,0 }, + { 857, 857, 0, 0, 8940, 386,0 }, + { 858, 858, 0, 0, 8966, 740,0 }, + { 859, 859, 0, 0, 40000, 273,0 }, + { 860, 860, 0, 0, 40000, 126,0 }, + { 861, 861, 0, 0, 40000, 400,0 }, + { 862, 862, 0, 0, 4480, 213,0 }, + { 863, 863, 0, 0, 633, 100,0 }, + { 864, 864, 0, 0, 3740, 353,0 }, + { 865, 865, 0, 0, 2333, 406,0 }, + { 866, 866, 0, 0, 1933, 566,0 }, + { 867, 867, 0, 0, 40000, 93,0 }, + { 868, 868, 0, 0, 40000, 106,0 }, + { 869, 869, 0, 0, 40000, 100,0 }, + { 870, 870, 0, 0, 3093, 240,0 }, + { 871, 871, 0, 0, 513, 93,0 }, + { 872, 872, 0, 0, 700, 180,0 }, + { 361, 361, 0, 0, 373, 40,0 }, + { 873, 873, 0, 0, 1046, 446,0 }, + { 874, 874, 0, 0, 1886, 520,0 }, + { 875, 875, 0, 0, 1226, 366,0 }, + { 876, 876, 0, 0, 4193, 73,0 }, + { 877, 877, 0, 0, 826, 120,0 }, + { 878, 878, 0, 0, 280, 146,0 }, + { 879, 879, 0, 0, 5266, 806,0 }, + { 880, 880, 0, 0, 386, 80,0 }, + { 881, 881, 0, 0, 40000, 100,0 }, + { 882, 882, 0, 0, 40000, 413,0 }, + { 883, 883, 0, 0, 40000, 0,0 }, + { 884, 884, 36, 0, 233, 80,0 }, + { 885, 885, 48, 0, 193, 93,0 }, + { 885, 885, 36, 0, 226, 100,0 }, + { 886, 886, 36, 0, 113, 0,0 }, + { 887, 887, 32, 0, 133, 40,0 }, + { 767, 767, 96, 0, 1760, 480,0 }, + { 888, 888, 30, 0, 246, 40,0 }, + { 889, 889, 35, 0, 420, 140,0 }, + { 890, 890, 60, 0, 240, 60,0 }, + { 884, 884, 59, 0, 146, 20,0 }, + { 890, 890, 44, 0, 240, 60,0 }, + { 891, 891, 41, 0, 713, 273,0 }, + { 892, 892, 47, 0, 173, 93,0 }, + { 891, 891, 44, 0, 513, 206,0 }, + { 891, 891, 48, 0, 506, 200,0 }, + { 893, 893, 62, 0, 1926, 93,0 }, + { 891, 891, 51, 0, 520, 200,0 }, + { 891, 891, 54, 0, 513, 206,0 }, + { 894, 894, 40, 0, 1280, 793,0 }, + { 891, 891, 57, 0, 380, 160,0 }, + { 895, 895, 97, 0, 233, 106,0 }, + { 896, 896, 50, 0, 220, 93,0 }, + { 376, 376, 60, 0, 1573, 713,0 }, + { 897, 897, 53, 0, 126, 73,0 }, + { 898, 898, 46, 0, 173, 133,0 }, + { 897, 897, 57, 0, 126, 33,0 }, + { 899, 899, 42, 0, 626, 233,0 }, + { 899, 899, 37, 0, 633, 240,0 }, + { 900, 900, 41, 0, 626, 240,0 }, + { 900, 900, 37, 0, 626, 240,0 }, + { 871, 871, 77, 0, 173, 40,0 }, + { 871, 871, 72, 0, 173, 40,0 }, + { 388, 388, 70, 0, 213, 86,0 }, + { 901, 901, 39, 0, 260, 26,0 }, + { 902, 902, 36, 0, 1093, 73,0 }, + { 903, 903, 46, 0, 120, 73,0 }, + { 904, 904, 48, 0, 766, 80,0 }, + { 905, 905, 85, 0, 126, 26,0 }, + { 361, 361, 66, 0, 180, 26,0 }, + { 906, 906, 41, 0, 193, 73,0 }, + { 907, 907, 41, 0, 333, 106,0 }, + { 908, 908, 81, 0, 160, 26,0 }, + { 400, 400, 10, 0, 1186, 413,0 }, + { 886, 886, 60, 0, 100, 0,0 }, + { 873, 873, 53, 0, 846, 360,0 }, + { 909, 909, 0, 0, 5593, 340,0 }, + { 910, 910, 0, 0, 14646, 346,0 }, + { 911, 911, 0, 0, 6826, 280,0 }, + { 912, 912, 0, 0, 7000, 306,0 }, + { 913, 913, 0, 0, 8793, 133,0 }, + { 914, 914, 0, 0, 14680, 346,0 }, + { 915, 915, 0, 0, 7246, 126,0 }, + { 916, 916, 0, 0, 40000, 0,0 }, + { 917, 917, 0, 0, 1866, 433,0 }, + { 362, 362, 0, 0, 1106, 340,0 }, + { 918, 918, 0, 0, 1053, 273,0 }, + { 919, 919, 0, 0, 14513, 1213,0 }, + { 920, 920, 0, 0, 1886, 646,0 }, + { 921, 921, 0, 0, 926, 313,0 }, + { 922, 922, 0, 0, 2340, 806,0 }, + { 923, 923, 0, 0, 2966, 553,0 }, + { 924, 924, 0, 0, 40000, 66,0 }, + { 925, 925, 0, 0, 40000, 73,0 }, + { 926, 926, 0, 0, 40000, 0,0 }, + { 927, 927, 0, 0, 40000, 126,0 }, + { 928, 928, 0, 0, 40000, 113,0 }, + { 929, 929, 0, 0, 40000, 113,0 }, + { 930, 930, 0, 0, 40000, 93,0 }, + { 931, 931, 0, 0, 40000, 113,0 }, + { 932, 932, 0, 0, 7200, 86,0 }, + { 933, 933, 0, 0, 5373, 106,0 }, + { 934, 934, 0, 0, 40000, 0,0 }, + { 935, 935, 0, 0, 40000, 0,0 }, + { 936, 936, 0, 0, 2380, 73,0 }, + { 937, 937, 0, 0, 40000, 0,0 }, + { 938, 938, 0, 0, 40000, 0,0 }, + { 939, 939, 0, 0, 6013, 53,0 }, + { 940, 940, 0, 0, 3713, 126,0 }, + { 941, 941, 0, 0, 17566, 26,0 }, + { 942, 942, 0, 0, 40000, 0,0 }, + { 943, 943, 0, 0, 40000, 0,0 }, + { 944, 944, 0, 0, 2506, 126,0 }, + { 945, 945, 0, 0, 3733, 73,0 }, + { 946, 946, 0, 0, 40000, 0,0 }, + { 947, 947, 0, 0, 3386, 80,0 }, + { 948, 948, 0, 0, 40000, 100,0 }, + { 949, 949, 0, 0, 40000, 100,0 }, + { 950, 950, 0, 0, 40000, 113,0 }, + { 951, 951, 0, 0, 40000, 0,0 }, + { 952, 952, 0, 0, 40000, 200,0 }, + { 953, 953, 0, 0, 1140, 213,0 }, + { 954, 954, 0, 0, 2140, 400,0 }, + { 955, 955, 0, 0, 813, 240,0 }, + { 956, 956, 0, 0, 40000, 100,0 }, + { 957, 957, 0, 0, 40000, 426,0 }, + { 958, 958, 0, 0, 40000, 0,0 }, + { 959, 959, 0, 0, 40000, 146,0 }, + { 960, 960, 0, 0, 40000, 120,0 }, + { 961, 961, 0, 0, 40000, 93,0 }, + { 962, 962, 0, 0, 1193, 153,0 }, + { 963, 963, 0, 0, 40000, 46,0 }, + { 964, 964, 0, 0, 40000, 80,0 }, + { 965, 965, 0, 0, 40000, 80,0 }, + { 966, 966, 0, 0, 40000, 20,0 }, + { 967, 967, 0, 0, 40000, 0,0 }, + { 968, 968, 0, 0, 40000, 93,0 }, + { 969, 969, 0, 0, 40000, 86,0 }, + { 970, 970, 0, 0, 40000, 213,0 }, + { 971, 971, 0, 0, 40000, 80,0 }, + { 972, 972, 0, 0, 40000, 73,0 }, + { 973, 973, 0, 0, 40000, 0,0 }, + { 974, 974, 0, 0, 40000, 93,0 }, + { 975, 975, 0, 0, 40000, 73,0 }, + { 976, 976, 0, 0, 40000, 73,0 }, + { 977, 977, 0, 0, 40000, 66,0 }, + { 978, 978, 0, 0, 40000, 66,0 }, + { 979, 979, 0, 0, 40000, 100,0 }, + { 980, 980, 0, 0, 40000, 73,0 }, + { 981, 981, 0, 0, 40000, 73,0 }, + { 982, 982, 0, 0, 40000, 80,0 }, + { 983, 983, 0, 0, 40000, 100,0 }, + { 984, 984, 0, 0, 40000, 100,0 }, + { 985, 985, 0, 0, 40000, 100,0 }, + { 986, 986, 0, 0, 40000, 80,0 }, + { 987, 987, 0, 0, 40000, 73,0 }, + { 988, 988, 0, 0, 40000, 0,0 }, + { 989, 989, 0, 0, 40000, 86,0 }, + { 990, 990, 0, 0, 40000, 0,0 }, + { 991, 991, 0, 0, 40000, 0,0 }, + { 992, 992, 0, 0, 40000, 80,0 }, + { 993, 993, 0, 0, 40000, 86,0 }, + { 994, 994, 0, 0, 40000, 0,0 }, + { 995, 995, 0, 0, 40000, 0,0 }, + { 996, 996, 0, 0, 40000, 333,0 }, + { 997, 997, 0, 0, 40000, 180,0 }, + { 998, 998, 0, 0, 40000, 80,0 }, + { 999, 999, 0, 0, 40000, 120,0 }, + {1000,1000, 0, 0, 10006, 460,0 }, + {1001,1001, 0, 0, 40000, 186,0 }, + {1002,1002, 0, 0, 40000, 400,0 }, + {1003,1003, 0, 0, 20333, 260,0 }, + {1004,1004, 0, 0, 40000, 373,0 }, + {1005,1005, 0, 0, 4520, 400,0 }, + {1006,1006, 0, 0, 8213, 306,0 }, + {1007,1007, 0, 0, 8646, 360,0 }, + {1008,1008, 0, 0, 40000, 160,0 }, + {1009,1009, 0, 0, 40000, 133,0 }, + {1010,1010, 0, 0, 40000, 400,0 }, + {1011,1011, 0, 0, 4473, 193,0 }, + {1012,1012, 0, 0, 1813, 0,0 }, + {1013,1013, 0, 0, 3726, 353,0 }, + {1014,1014, 0, 0, 4400, 373,0 }, + {1015,1015, 0, 0, 953, 166,0 }, + {1016,1016, 0, 0, 40000, 73,0 }, + {1017,1017, 0, 0, 40000, 100,0 }, + {1018,1018, 0, 0, 40000, 100,0 }, + {1019,1019, 0, 0, 3100, 240,0 }, + { 444, 444, 0, 0, 513, 93,0 }, + {1020,1020, 0, 0, 626, 180,0 }, + { 449, 449, 0, 0, 373, 80,0 }, + { 453, 453, 0, 0, 40000, 0,0 }, + {1021,1021, 0, 0, 1020, 340,0 }, + {1022,1022, 0, 0, 1200, 366,0 }, + {1023,1023, 0, 0, 4193, 73,0 }, + {1024,1024, 0, 0, 820, 120,0 }, + {1025,1025, 0, 0, 680, 213,0 }, + {1026,1026, 0, 0, 5260, 806,0 }, + {1027,1027, 0, 0, 9193, 86,0 }, + {1028,1028, 0, 0, 40000, 100,0 }, + {1029,1029, 0, 0, 40000, 426,0 }, + {1030,1030, 0, 0, 40000, 260,0 }, + {1031,1031, 0, 0, 3480, 66,0 }, + {1032,1032, 32, 0, 133, 46,0 }, + {1033,1033, 30, 0, 200, 40,0 }, + {1034,1034, 96, 0, 146, 73,0 }, + {1035,1035, 60, 0, 553, 186,0 }, + {1036,1036, 0, 0, 13193, 260,0 }, + {1037,1037, 0, 0, 40000, 100,0 }, + {1038,1038, 0, 0, 7980, 66,0 }, + {1039,1039, 0, 0, 40000, 0,0 }, + {1040,1040, 0, 0, 980, 340,0 }, + {1041,1041, 0, 0, 7413, 2480,0 }, + {1042,1042, 0, 0, 2906, 520,0 }, + {1043,1043, 0, 0, 40000, 73,0 }, + {1044,1044, 0, 0, 40000, 53,0 }, + {1045,1045, 0, 0, 40000, 113,0 }, + {1046,1046, 0, 0, 5380, 113,0 }, + {1047,1047, 0, 0, 40000, 0,0 }, + {1048,1048, 0, 0, 2366, 73,0 }, + {1049,1049, 0, 0, 40000, 0,0 }, + {1050,1050, 0, 0, 18293, 80,0 }, + {1051,1051, 0, 0, 18466, 146,0 }, + {1052,1052, 0, 0, 9220, 73,0 }, + {1053,1053, 0, 0, 40000, 240,0 }, + {1054,1054, 0, 0, 40000, 0,0 }, + {1055,1055, 0, 0, 1086, 126,0 }, + {1056,1056, 0, 0, 3766, 73,0 }, + {1057,1057, 0, 0, 1186, 226,0 }, + {1058,1058, 0, 0, 3373, 73,0 }, + {1059,1059, 0, 0, 40000, 246,0 }, + {1060,1060, 0, 0, 340, 220,0 }, + {1061,1061, 0, 0, 1186, 386,0 }, + {1062,1062, 0, 0, 40000, 253,0 }, + {1063,1063, 0, 0, 40000, 440,0 }, + {1064,1064, 0, 0, 40000, 46,0 }, + {1065,1065, 0, 0, 40000, 80,0 }, + {1066,1066, 0, 0, 40000, 126,0 }, + {1067,1067, 0, 0, 40000, 133,0 }, + {1068,1068, 0, 0, 40000, 93,0 }, + {1069,1069, 0, 0, 40000, 86,0 }, + {1070,1070, 0, 0, 40000, 93,0 }, + {1071,1071, 0, 0, 40000, 66,0 }, + {1072,1072, 0, 0, 40000, 93,0 }, + {1073,1073, 0, 0, 40000, 73,0 }, + {1074,1074, 0, 0, 40000, 173,0 }, + {1075,1075, 0, 0, 586, 193,0 }, + {1076,1076, 0, 0, 40000, 146,0 }, + {1077,1077, 0, 0, 18460, 73,0 }, + {1078,1078, 0, 0, 846, 93,0 }, + {1079,1079, 0, 0, 40000, 0,0 }, + {1080,1080, 0, 0, 40000, 86,0 }, + {1081,1081, 0, 0, 40000, 0,0 }, + {1082,1082, 0, 0, 40000, 353,0 }, + {1083,1083, 0, 0, 40000, 300,0 }, + {1084,1084, 0, 0, 40000, 320,0 }, + {1085,1085, 0, 0, 9920, 1553,0 }, + {1086,1086, 0, 0, 40000, 386,0 }, + {1087,1087, 0, 0, 40000, 0,0 }, + {1088,1088, 0, 0, 9980, 873,0 }, + {1089,1089, 0, 0, 40000, 386,0 }, + {1090,1090, 0, 0, 966, 126,0 }, + {1091,1091, 0, 0, 40000, 820,0 }, + {1092,1092, 0, 0, 8620, 366,0 }, + {1093,1093, 0, 0, 40000, 826,0 }, + {1094,1094, 0, 0, 40000, 433,0 }, + {1095,1095, 0, 0, 633, 73,0 }, + {1096,1096, 0, 0, 3693, 126,0 }, + {1097,1097, 0, 0, 40000, 0,0 }, + {1098,1098, 0, 0, 40000, 153,0 }, + {1099,1099, 0, 0, 40000, 0,0 }, + {1100,1100, 0, 0, 40000, 0,0 }, + {1101,1101, 0, 0, 40000, 306,0 }, + {1102,1102, 0, 0, 3666, 3093,0 }, + {1103,1103, 0, 0, 1873, 653,0 }, + {1104,1104, 0, 0, 40000, 0,0 }, + {1105,1105, 0, 0, 11293, 886,0 }, + {1106,1106, 0, 0, 40000, 546,0 }, + { 430, 430, 0, 0, 1146, 80,0 }, + {1107,1107, 35, 0, 580, 80,0 }, + {1090,1090, 77, 0, 280, 60,0 }, + {1090,1090, 72, 0, 280, 60,0 }, + {1108,1108, 0, 0, 10180, 600,0 }, + {1109,1109, 0, 0, 10053, 353,0 }, + {1110,1111, 0, 1, 9940, 480,0 }, + {1112,1113, 0, 1, 10620, 473,0.03125 }, + {1114,1114, 0, 0, 40000, 0,0 }, + {1115,1116, 0, 1, 9833, 220,0 }, + {1117,1117, 0, 0, 10286, 473,0 }, + {1118,1118, 0, 0, 7686, 93,0 }, + {1119,1119, 0, 0, 7220, 613,0 }, + {1120,1120, 0, 0, 11513, 1666,0 }, + {1121,1121, 0, 0, 5200, 1700,0 }, + {1122,1122, 0, 0, 10173, 626,0 }, + {1123,1123, 0, 0, 1206, 380,0 }, + {1124,1124, 0, 0, 1953, 866,0 }, + {1125,1125, 0, 0, 4686, 1586,0 }, + {1126,1126, 0, 0, 3786, 893,0 }, + {1127,1127, 0, 0, 40000, 126,0 }, + {1128,1128, 0, 0, 40000, 120,0 }, + {1129,1130, 0, 1, 40000, 146,0.15625 }, + {1131,1131, 0, 0, 40000, 433,0 }, + {1132,1132, 0, 0, 40000, 133,0 }, + {1133,1134, 0, 1, 40000, 126,-0.046875 }, + {1135,1135, 0, 0, 40000, 113,0 }, + {1136,1137, 0, 1, 40000, 253,2.5e-05 }, + {1138,1138, 0, 0, 18440, 240,0 }, + {1139,1139, 0, 0, 5213, 886,0 }, + {1140,1140, 0, 0, 1446, 113,0 }, + {1141,1141, 0, 0, 5233, 106,0 }, + {1142,1142, 0, 0, 5286, 266,0 }, + {1143,1143, 0, 0, 40000, 66,0 }, + {1144,1144, 0, 0, 40000, 66,0 }, + {1145,1145, 0, 0, 10593, 106,0 }, + {1146,1146, 0, 0, 2733, 160,0 }, + {1147,1147, 0, 0, 10313, 93,0 }, + {1148,1148, 0, 0, 40000, 0,0 }, + {1149,1150, 0, 1, 40000, 0,-0.03125 }, + {1151,1151, 0, 0, 40000, 53,0 }, + {1152,1152, 0, 0, 10560, 246,0 }, + {1153,1153, 0, 0, 2700, 153,0 }, + {1154,1154, 0, 1, 40000, 100,-0.15625 }, + {1155,1155, 0, 0, 40000, 73,0 }, + {1156,1156, 0, 0, 40000, 220,0 }, + {1157,1157, 0, 0, 40000, 140,0 }, + {1158,1158, 0, 0, 40000, 380,0 }, + {1159,1160, 0, 1, 40000, 400,0.171875 }, + {1161,1161, 0, 0, 40000, 0,0 }, + {1162,1162, 0, 0, 40000, 0,0 }, + {1163,1163, 0, 0, 4733, 906,0 }, + {1164,1165, 0, 1, 40000, 393,-0.125 }, + {1166,1167, 0, 1, 40000, 366,0.078125 }, + {1168,1168, 0, 1, 40000, 2453,-0.078125 }, + {1169,1170, 0, 1, 40000, 546,0.0625 }, + {1171,1172, 0, 1, 40000, 786,0.15625 }, + {1173,1173, 0, 0, 40000, 0,0 }, + {1174,1174, 0, 0, 40000, 513,0 }, + {1175,1176, 0, 1, 2300, 533,0 }, + {1177,1177, 0, 0, 40000, 80,0 }, + {1178,1178, 0, 0, 40000, 60,0 }, + {1179,1179, 0, 0, 40000, 0,0 }, + {1180,1180, 0, 0, 10653, 86,0 }, + {1181,1182, 0, 1, 40000, 0,2.5e-05 }, + {1183,1184, 0, 1, 40000, 86,0.046875 }, + {1185,1186, 0, 1, 40000, 0,0.09375 }, + {1187,1188, 0, 1, 40000, 0,0.09375 }, + {1189,1189, 0, 0, 40000, 133,0 }, + {1190,1190, 0, 0, 40000, 140,0 }, + {1191,1191, 0, 0, 40000, 73,0 }, + {1192,1192, 0, 0, 40000, 60,0 }, + {1193,1193, 0, 0, 40000, 106,0 }, + {1194,1194, 0, 0, 40000, 93,0 }, + {1195,1195, 0, 0, 40000, 66,0 }, + {1196,1196, 0, 0, 40000, 93,0 }, + {1197,1197, 0, 0, 40000, 60,0 }, + {1198,1198, 0, 0, 40000, 66,0 }, + {1199,1199, 0, 0, 40000, 120,0 }, + {1200,1200, 0, 0, 40000, 100,0 }, + {1201,1201, 0, 0, 40000, 86,0 }, + {1202,1202, 0, 0, 40000, 0,0 }, + {1203,1203, 0, 0, 40000, 233,0 }, + {1204,1204, 0, 0, 40000, 100,0 }, + {1205,1206, 0, 1, 40000, 266,0.03125 }, + {1207,1208, 0, 1, 40000, 260,-2.5e-05 }, + {1209,1209, 0, 0, 40000, 146,0 }, + {1210,1211, 0, 1, 40000, 60,0.03125 }, + {1212,1212, 0, 0, 40000, 53,0 }, + {1213,1214, 0, 1, 40000, 706,-0.09375 }, + {1215,1216, 0, 1, 40000, 660,-0.046875 }, + {1217,1217, 0, 0, 40000, 133,0 }, + {1218,1219, 0, 1, 40000, 426,0.03125 }, + {1220,1220, 0, 1, 40000, 0,0.03125 }, + {1221,1222, 0, 1, 40000, 260,0.171875 }, + {1223,1223, 0, 0, 40000, 0,0 }, + {1224,1224, 0, 0, 6100, 1580,0 }, + {1225,1150, 0, 1, 40000, 73,-0.03125 }, + {1226,1226, 0, 0, 40000, 1580,0 }, + {1227,1227, 0, 0, 40000, 40,0 }, + {1228,1229, 0, 1, 40000, 113,0.125 }, + {1230,1230, 0, 0, 2666, 846,0 }, + {1231,1232, 0, 1, 40000, 0,-0.03125 }, + {1233,1234, 0, 1, 9233, 2413,-0.1875 }, + {1235,1235, 0, 0, 40000, 1020,0 }, + {1236,1236, 0, 0, 40000, 0,0 }, + {1237,1237, 0, 0, 9633, 3073,0 }, + {1238,1238, 0, 0, 40000, 0,0 }, + {1239,1239, 0, 0, 2446, 386,0 }, + {1240,1241, 0, 1, 3113, 1133,0 }, + {1242,1242, 0, 0, 18473, 813,0 }, + {1243,1243, 0, 0, 1206, 660,0 }, + {1244,1244, 0, 0, 40000, 153,0 }, + {1245,1245, 0, 0, 40000, 160,0 }, + {1246,1246, 0, 0, 40000, 133,0 }, + {1247,1247, 0, 0, 8660, 2386,0 }, + {1248,1248, 0, 0, 293, 106,0 }, + {1249,1249, 0, 0, 40000, 433,0 }, + {1250,1250, 0, 0, 426, 80,0 }, + {1251,1251, 0, 0, 973, 360,0 }, + {1252,1252, 0, 0, 573, 153,0 }, + {1253,1253, 0, 0, 3746, 126,0 }, + {1254,1254, 0, 0, 2313, 73,0 }, + {1255,1255, 0, 0, 1473, 106,0 }, + {1256,1256, 0, 0, 1500, 320,0 }, + {1257,1257, 0, 0, 5280, 1593,0 }, + {1258,1258, 0, 0, 40000, 60,0 }, + {1259,1259, 0, 0, 40000, 146,0 }, + {1260,1260, 29, 0, 40000, 300,0 }, + {1261,1261, 65, 0, 40000, 2040,0 }, + {1262,1262, 0, 0, 626, 240,0 }, + {1263,1263, 25, 0, 626, 226,0 }, + {1264,1264, 83, 0, 180, 80,0 }, + {1265,1265, 32, 0, 260, 140,0 }, + {1266,1266, 60, 0, 40000, 0,0 }, + {1267,1267, 36, 0, 286, 40,0 }, + {1268,1268, 27, 0, 573, 80,0 }, + {1269,1269, 31, 0, 693, 106,0 }, + {1270,1270, 21, 0, 500, 146,0 }, + {1270,1270, 26, 0, 493, 140,0 }, + {1270,1270, 28, 0, 500, 146,0 }, + {1271,1271, 60, 0, 2420, 1080,0 }, + {1270,1270, 32, 0, 413, 126,0 }, + {1272,1272, 60, 0, 806, 300,0 }, + {1273,1273, 96, 0, 1146, 493,0 }, + {1274,1274, 72, 0, 1246, 586,0 }, + {1275,1275, 79, 0, 286, 106,0 }, + {1276,1276, 69, 0, 1193, 1046,0 }, + {1277,1277, 71, 0, 340, 93,0 }, + {1278,1278, 22, 0, 1880, 653,0 }, + {1279,1279, 55, 0, 246, 120,0 }, + {1279,1279, 48, 0, 286, 133,0 }, + {1280,1280, 0, 0, 40, 0,0 }, + {1281,1281, 49, 2, 40, 0,0 }, + {1282,1282, 73, 0, 166, 33,0 }, + {1282,1282, 68, 0, 166, 33,0 }, + {1282,1282, 61, 0, 200, 40,0 }, + {1283,1283, 0, 0, 40, 0,0 }, + {1284,1284, 0, 0, 40000, 100,0 }, + {1285,1285, 0, 0, 40000, 60,0 }, + {1286,1286, 0, 0, 40000, 0,0 }, + {1287,1287, 0, 0, 10460, 153,0 }, + {1288,1289, 0, 1, 40000, 0,0 }, + {1290,1290, 0, 0, 40000, 0,0 }, + {1291,1292, 36, 1, 353, 153,0 }, + {1293,1293, 69, 0, 1206, 1060,0 }, + {1294,1294, 0, 0, 40000, 0,0 }, + {1295,1295, 0, 0, 40000, 73,0 }, + {1296,1296, 0, 0, 40000, 0,0 }, + {1297,1297, 22, 0, 1880, 653,0 }, + {1298,1298, 0, 0, 40000, 73,0 }, + {1299,1299, 0, 0, 3913, 420,0 }, + {1300,1300, 0, 0, 9233, 240,0 }, + {1301,1301, 0, 0, 4660, 1573,0 }, + {1302,1302, 0, 0, 1166, 400,0 }, + {1303,1303, 0, 0, 40000, 126,0 }, + {1304,1304, 0, 0, 40000, 93,0 }, + {1305,1305, 0, 0, 40000, 93,0 }, + {1306,1306, 0, 0, 40000, 553,0 }, + {1307,1307, 0, 0, 40000, 660,0 }, + {1308,1308, 0, 0, 40000, 73,0 }, + {1309,1309, 0, 0, 40000, 146,0 }, + {1310,1310, 0, 0, 40000, 146,0 }, + {1311,1311, 0, 0, 4026, 100,0 }, + {1312,1312, 0, 0, 18226, 100,0 }, + {1313,1313, 0, 0, 40000, 0,0 }, + {1314,1314, 0, 0, 40000, 73,0 }, + {1315,1315, 0, 0, 40000, 140,0 }, + {1316,1316, 0, 0, 40000, 393,0 }, + {1317,1317, 0, 0, 40000, 406,0 }, + {1318,1318, 0, 0, 40000, 373,0 }, + {1319,1319, 0, 0, 40000, 0,0 }, + {1320,1320, 0, 0, 40000, 360,0 }, + {1321,1321, 0, 0, 1060, 380,0 }, + {1322,1322, 0, 0, 40000, 66,0 }, + {1323,1323, 0, 0, 40000, 66,0 }, + {1324,1324, 0, 0, 40000, 86,0 }, + {1325,1325, 0, 0, 40000, 73,0 }, + { 260, 260, 0, 0, 40000, 80,0 }, + {1326,1326, 0, 0, 40000, 80,0 }, + {1327,1327, 0, 0, 40000, 73,0 }, + {1328,1328, 0, 0, 40000, 73,0 }, + {1329,1329, 0, 0, 40000, 153,0 }, + {1330,1330, 0, 0, 40000, 153,0 }, + {1331,1331, 0, 0, 40000, 146,0 }, + {1332,1332, 0, 0, 40000, 146,0 }, + {1333,1333, 0, 0, 40000, 73,0 }, + {1334,1334, 0, 0, 40000, 153,0 }, + {1335,1335, 0, 0, 40000, 233,0 }, + {1336,1336, 0, 0, 40000, 400,0 }, + {1337,1337, 0, 0, 40000, 1373,0 }, + {1338,1338, 0, 0, 40000, 193,0 }, + {1339,1339, 0, 0, 40000, 1273,0 }, + {1340,1340, 0, 0, 40000, 186,0 }, + {1341,1341, 0, 0, 40000, 86,0 }, + {1342,1342, 0, 0, 7440, 2473,0 }, + {1343,1343, 0, 0, 40000, 160,0 }, + {1344,1344, 0, 0, 8966, 406,0 }, + {1345,1345, 0, 0, 40000, 1353,0 }, + {1346,1346, 0, 0, 14180, 4406,0 }, + { 378, 378, 84, 0, 1333, 460,0 }, + {1347,1347, 24, 0, 1893, 633,0 }, + {1348,1348, 44, 0, 206, 86,0 }, + {1349,1349, 40, 0, 586, 140,0 }, + {1350,1350, 60, 0, 1026, 320,0 }, + {1351,1351, 0, 0, 6560, 33,0 }, + {1352,1352, 0, 0, 7373, 2453,0 }, + {1353,1353, 0, 0, 4660, 1573,0 }, + {1354,1354, 0, 0, 40000, 346,0 }, + {1355,1355, 0, 0, 7126, 86,0 }, + {1356,1356, 0, 0, 40000, 213,0 }, + {1357,1357, 0, 0, 1180, 340,0 }, + {1358,1358, 0, 0, 3893, 1466,0 }, + {1359,1359, 0, 0, 2053, 1173,0 }, + {1360,1360, 0, 0, 40000, 200,0 }, + {1361,1361, 0, 0, 40000, 353,0 }, + {1362,1362, 0, 0, 40000, 273,0 }, + {1363,1363, 0, 0, 40000, 433,0 }, + {1364,1364, 0, 0, 1940, 426,0 }, + {1365,1365, 0, 0, 40000, 80,0 }, + {1366,1366, 0, 0, 40000, 106,0 }, + {1367,1367, 0, 0, 40000, 60,0 }, + {1368,1368, 0, 0, 40000, 140,0 }, + {1369,1369, 0, 0, 40000, 93,0 }, + {1370,1370, 0, 0, 40000, 73,0 }, + {1371,1371, 0, 0, 40000, 73,0 }, + {1372,1372, 0, 0, 40000, 93,0 }, + {1373,1373, 0, 0, 40000, 73,0 }, + {1374,1374, 0, 0, 40000, 80,0 }, + {1375,1375, 0, 0, 40000, 746,0 }, + {1376,1376, 0, 0, 2360, 813,0 }, + {1377,1377, 0, 0, 340, 146,0 }, + {1378,1378, 35, 0, 713, 273,0 }, + {1379,1379, 49, 0, 173, 93,0 }, + {1377,1377, 48, 0, 286, 126,0 }, + {1380,1380, 58, 0, 173, 100,0 }, + {1377,1377, 60, 0, 286, 133,0 }, + {1381,1381, 47, 0, 973, 360,0 }, + {1382,1382, 60, 0, 146, 86,0 }, + {1381,1381, 49, 0, 966, 333,0 }, + {1383,1383, 72, 0, 506, 206,0 }, + {1381,1381, 51, 0, 953, 340,0 }, + {1384,1384, 84, 0, 1340, 480,0 }, + {1381,1381, 54, 0, 986, 360,0 }, + {1381,1381, 57, 0, 980, 346,0 }, + {1385,1385, 72, 0, 1573, 440,0 }, + {1381,1381, 60, 0, 953, 340,0 }, + {1386,1386, 36, 0, 2673, 900,0 }, + {1387,1387, 93, 0, 233, 106,0 }, + {1388,1388, 72, 0, 966, 353,0 }, + {1389,1389, 84, 0, 1366, 473,0 }, + {1390,1390, 36, 0, 1326, 446,0 }, + {1391,1391, 64, 0, 220, 86,0 }, + {1392,1392, 68, 0, 126, 220,0 }, + {1393,1393, 0, 0, 4513, 640,0 }, + {1394,1394, 0, 0, 40000, 353,0 }, + {1395,1395, 0, 0, 40000, 73,0 }, + {1396,1396, 0, 0, 2040, 380,0 }, + {1397,1397, 0, 0, 40000, 240,0 }, + {1398,1398, 0, 0, 3246, 753,0 }, + {1399,1399, 0, 0, 40000, 66,0 }, + {1400,1400, 0, 0, 40000, 0,0 }, + {1401,1401, 0, 0, 40000, 0,0 }, + {1402,1402, 0, 0, 7720, 1260,0 }, + {1403,1403, 0, 0, 213, 6420,0 }, + {1404,1404, 0, 0, 40000, 66,0 }, + {1405,1405, 0, 0, 40000, 73,0 }, + {1406,1406, 0, 0, 40000, 93,0 }, + {1407,1407, 0, 0, 1606, 640,0 }, + {1408,1408, 0, 0, 15486, 1580,0 }, + {1409,1409, 0, 0, 40000, 353,0 }, + {1410,1410, 0, 0, 40000, 2066,0 }, + {1411,1411, 0, 0, 40000, 0,0 }, + {1412,1412, 0, 0, 15453, 73,0 }, + {1413,1413, 0, 0, 3726, 1240,0 }, + {1414,1414, 0, 0, 40000, 86,0 }, + {1415,1415, 0, 0, 40000, 200,0 }, + {1416,1416, 0, 0, 40000, 53,0 }, + {1417,1417, 0, 0, 40000, 73,0 }, + {1418,1418, 0, 0, 40000, 66,0 }, + {1419,1419, 0, 0, 40000, 26,0 }, + {1420,1420, 0, 0, 40000, 53,0 }, + {1421,1421, 0, 0, 40000, 40,0 }, + {1422,1422, 0, 0, 40000, 126,0 }, + {1423,1423, 0, 0, 40000, 0,0 }, + {1424,1424, 0, 0, 13653, 0,0 }, + {1425,1425, 0, 0, 12533, 1953,0 }, + {1426,1426, 0, 0, 973, 1280,0 }, + {1427,1427, 0, 0, 40000, 426,0 }, + {1428,1428, 0, 0, 40000, 53,0 }, + {1429,1429, 0, 0, 40000, 66,0 }, + {1430,1430, 0, 0, 526, 840,0 }, + {1431,1431, 0, 0, 286, 1293,0 }, + {1432,1432, 0, 0, 14726, 4920,0 }, + {1433,1433, 0, 0, 5233, 633,0 }, + {1434,1434, 0, 0, 13226, 2500,0 }, + { 740, 740, 0, 0, 513, 200,0 }, + {1435,1435, 0, 0, 40000, 5666,0 }, + { 739, 739, 48, 0, 213, 20,0 }, + { 500, 500, 55, 0, 100, 0,0 }, + { 740, 740, 60, 0, 226, 113,0 }, + { 500, 500, 41, 0, 106, 0,0 }, + {1436,1436, 84, 0, 160, 26,0 }, + {1437,1437, 84, 0, 386, 493,0 }, + { 500, 500, 48, 0, 100, 0,0 }, + {1438,1438, 15, 0, 340, 140,0 }, + { 752, 752, 49, 0, 173, 20,0 }, + {1438,1438, 16, 0, 346, 146,0 }, + {1438,1438, 12, 0, 340, 140,0 }, + { 740, 740, 55, 0, 220, 113,0 }, + { 752, 752, 18, 0, 206, 20,0 }, + { 752, 752, 15, 0, 200, 20,0 }, + { 752, 752, 17, 0, 206, 20,0 }, + {1439,1440, 0, 4, 40000, 0,0 }, + {1441,1442, 0, 4, 7360, 200,0 }, + {1443,1444, 0, 4, 11840, 320,0 }, + {1445,1446, 0, 4, 9920, 326,0 }, + {1447,1448, 0, 4, 10213, 0,0 }, + {1449,1450, 0, 4, 7440, 2486,0 }, + { 181,1451, 0, 4, 2360, 733,0 }, + {1452,1453, 0, 4, 9260, 240,0 }, + {1454,1455, 0, 4, 40000, 0,0 }, + {1456,1457, 0, 4, 660, 126,0 }, + {1458,1459, 0, 4, 40000, 66,0 }, + { 190,1460, 0, 4, 40000, 60,0 }, + { 192,1461, 0, 4, 40000, 73,0 }, + {1462,1463, 0, 4, 40000, 353,0 }, + {1464,1465, 0, 4, 40000, 353,0 }, + {1466,1467, 0, 4, 40000, 66,0 }, + {1468,1469, 0, 4, 40000, 46,0 }, + { 35,1470, 0, 4, 40000, 46,0 }, + { 36,1471, 0, 4, 320, 0,0 }, + {1472,1473, 0, 4, 320, 0,0 }, + {1474,1475, 0, 4, 7986, 93,0 }, + { 39,1476, 0, 4, 1053, 226,0 }, + {1477,1476, 0, 4, 1060, 226,0 }, + {1478,1479, 0, 4, 40000, 453,0 }, + { 50,1480, 0, 4, 40000, 400,0 }, + {1481,1482, 0, 4, 40000, 133,0 }, + {1483,1484, 0, 4, 40000, 0,0 }, + {1485,1486, 0, 4, 40000, 226,0 }, + { 55,1487, 0, 4, 40000, 100,0 }, + {1488,1489, 0, 4, 40000, 93,0 }, + {1490,1491, 0, 4, 40000, 73,0 }, + {1492,1493, 0, 4, 40000, 73,0 }, + {1494,1495, 0, 4, 40000, 73,0 }, + {1496,1497, 0, 4, 40000, 80,0 }, + {1496,1498, 0, 4, 40000, 73,0 }, + {1499,1500, 0, 4, 40000, 66,0 }, + {1501,1502, 0, 4, 40000, 146,0 }, + {1503,1504, 0, 4, 40000, 93,0 }, + {1505,1506, 0, 4, 40000, 73,0 }, + { 86,1507, 0, 4, 40000, 80,0 }, + {1508,1509, 0, 4, 40000, 0,0 }, + {1510,1511, 0, 4, 40000, 60,0 }, + {1512,1513, 0, 4, 40000, 0,0 }, + {1514,1515, 0, 4, 40000, 0,0 }, + {1516,1517, 0, 4, 40000, 773,0 }, + {1518,1519, 0, 4, 5346, 2973,0 }, + {1520,1521, 0, 4, 40000, 406,0 }, + {1522,1523, 0, 4, 9080, 360,0 }, + {1524,1525, 0, 4, 40000, 1200,0 }, + {1526,1527, 0, 4, 40000, 800,0 }, + {1528,1529, 0, 4, 40000, 960,0 }, + { 111,1530, 0, 4, 1200, 433,0 }, + {1531,1532, 0, 4, 226, 386,0 }, + { 115,1533, 0, 4, 2433, 0,0 }, + {1534,1535, 0, 4, 1873, 646,0 }, + {1536,1537, 0, 4, 3013, 53,0 }, + {1538,1539, 0, 4, 1560, 720,0 }, + {1540, 339, 0, 6, 6, 0,0 }, + {1541, 339, 0, 6, 6, 0,0 }, + {1542,1543, 0, 4, 993, 93,0 }, + {1544,1545, 0, 4, 293, 86,0 }, + {1546,1547, 0, 4, 40000, 153,0 }, + { 364, 365, 44, 4, 120, 0,0 }, + { 129,1548, 48, 4, 173, 0,0 }, + { 367, 368, 58, 4, 173, 0,0 }, + { 129,1549, 60, 4, 173, 0,0 }, + {1550,1551, 48, 4, 520, 200,0 }, + { 132,1552, 43, 4, 173, 0,0 }, + {1550,1551, 49, 4, 520, 200,0 }, + {1553,1554, 43, 4, 160, 80,0 }, + {1550,1551, 51, 4, 513, 0,0 }, + { 134,1555, 43, 4, 1733, 0,0 }, + {1550,1551, 54, 4, 506, 0,0 }, + {1550,1551, 57, 4, 506, 0,0 }, + { 380, 381, 72, 4, 1580, 0,0 }, + {1550,1551, 60, 4, 520, 0,0 }, + {1556,1557, 70, 4, 826, 306,0 }, + { 374, 375, 60, 4, 973, 0,0 }, + {1558,1559, 36, 4, 1233, 0,0 }, + {1560,1561, 65, 4, 293, 133,0 }, + {1562,1563, 84, 4, 1360, 0,0 }, + {1564,1565, 59, 4, 380, 0,0 }, + {1566,1567, 84, 4, 1593, 566,0 }, + {1568,1569, 35, 4, 1353, 473,0 }, + {1570,1571, 44, 4, 413, 0,0 }, + {1572,1573, 67, 4, 246, 0,0 }, + {1574,1575, 66, 4, 293, 0,0 }, + { 145,1576, 59, 4, 146, 0,0 }, + {1577,1578, 51, 4, 360, 0,0 }, + {1579,1580, 45, 4, 246, 0,0 }, + {1581,1582, 71, 4, 433, 0,0 }, + { 149,1583, 60, 4, 280, 0,0 }, + {1584,1585, 58, 4, 173, 0,0 }, + {1586,1587, 53, 4, 173, 0,0 }, + { 397,1588, 64, 4, 220, 80,0 }, + {1589,1590, 71, 4, 106, 53,0 }, + {1591,1592, 61, 4, 1000, 340,0 }, + {1593,1594, 61, 4, 1000, 340,0 }, + { 391, 392, 48, 4, 160, 46,0 }, + { 391, 393, 48, 4, 380, 60,0 }, + {1595,1596, 69, 4, 120, 0,0 }, + { 159,1597, 68, 4, 120, 0,0 }, + { 159,1597, 63, 4, 140, 0,0 }, + {1598,1599, 74, 4, 893, 273,0 }, + {1600,1601, 60, 4, 1013, 306,0 }, + {1602,1603, 80, 4, 220, 0,0 }, + {1604,1605, 64, 4, 1366, 0,0 }, + {1606,1607, 69, 4, 120, 73,0 }, + { 398, 399, 55, 4, 1540, 193,0 }, + {1608,1609, 75, 4, 1573, 0,0 }, + {1610,1611, 68, 4, 120, 0,0 }, + {1612,1613, 48, 4, 360, 0,0 }, + {1614,1615, 53, 4, 606, 0,0 }, + {1616,1616, 0, 0, 40000, 1586,0 }, + {1617,1617, 0, 0, 40000, 1226,0 }, + {1618,1618, 0, 0, 4546, 766,0 }, + {1619,1619, 0, 0, 40000, 420,0 }, + {1620,1620, 0, 0, 40000, 1573,0 }, + {1621,1621, 0, 0, 3326, 806,0 }, + {1622,1622, 0, 0, 40000, 746,0 }, + {1623,1623, 0, 0, 40000, 900,0 }, + {1624,1624, 0, 0, 12166, 1573,0 }, + {1625,1625, 0, 0, 40000, 80,0 }, + {1626,1626, 0, 0, 40000, 80,0 }, + {1627,1627, 0, 0, 40000, 80,0 }, + {1628,1628, 0, 0, 40000, 2713,0 }, + {1629,1629, 0, 0, 40000, 86,0 }, + {1630,1630, 0, 0, 40000, 80,0 }, + {1631,1631, 0, 0, 40000, 80,0 }, + {1632,1632, 0, 0, 40000, 813,0 }, + {1633,1633, 0, 0, 40000, 80,0 }, + {1634,1634, 0, 0, 40000, 80,0 }, + {1635,1635, 0, 0, 40000, 80,0 }, + {1636,1636, 0, 0, 40000, 193,0 }, + {1637,1637, 0, 0, 2920, 733,0 }, + {1638,1638, 0, 0, 40000, 373,0 }, + {1639,1639, 0, 0, 2286, 226,0 }, + {1640,1640, 0, 0, 40000, 226,0 }, + {1641,1641, 0, 0, 40000, 226,0 }, + {1642,1642, 0, 0, 40000, 433,0 }, + {1643,1643, 0, 0, 40000, 813,0 }, + {1644,1644, 0, 0, 40000, 80,0 }, + {1645,1645, 0, 0, 40000, 80,0 }, + {1646,1646, 0, 0, 40000, 80,0 }, + {1647,1647, 0, 0, 40000, 80,0 }, + {1648,1648, 0, 0, 40000, 80,0 }, + {1649,1649, 0, 0, 40000, 80,0 }, + {1650,1650, 0, 0, 40000, 146,0 }, + {1651,1651, 0, 0, 40000, 1280,0 }, + {1652,1652, 0, 0, 40000, 513,0 }, + {1653,1653, 0, 0, 40000, 313,0 }, + {1654,1654, 0, 0, 40000, 773,0 }, + {1655,1655, 0, 0, 7400, 2480,0 }, + {1656,1656, 0, 0, 3760, 1253,0 }, + {1657,1657, 0, 0, 40000, 380,0 }, + {1658,1658, 0, 0, 40000, 333,0 }, + {1659,1659, 0, 0, 40000, 2926,0 }, + {1660,1660, 0, 0, 40000, 5666,0 }, + {1661,1661, 0, 0, 40000, 1613,0 }, + {1662,1662, 0, 0, 3746, 1273,0 }, + {1663,1663, 0, 0, 13653, 0,0 }, + {1664,1664, 0, 0, 4640, 1553,0 }, + {1665,1665, 0, 0, 40000, 680,0 }, + {1666,1666, 0, 0, 6393, 426,0 }, + {1667,1667, 0, 0, 40000, 713,0 }, + {1668,1668, 12, 0, 166, 20,0 }, + {1669,1669, 48, 0, 460, 193,0 }, + { 736, 736, 52, 0, 286, 20,0 }, + {1670,1670, 48, 0, 506, 200,0 }, + {1670,1670, 36, 0, 713, 260,0 }, + { 377, 377, 84, 0, 386, 493,0 }, + { 730, 730, 95, 0, 1886, 653,0 }, + {1669,1669, 84, 0, 386, 166,0 }, + { 755, 755, 20, 0, 633, 240,0 }, + { 755, 755, 22, 0, 626, 240,0 }, + { 755, 755, 24, 0, 633, 246,0 }, + {1671,1671, 0, 0, 2233, 220,0 }, + {1672,1672, 0, 0, 2233, 240,0 }, + {1673,1673, 0, 0, 2233, 206,0 }, + {1674,1674, 0, 0, 2126, 173,0 }, + {1675,1675, 0, 0, 7473, 73,0 }, + {1676,1676, 0, 0, 40000, 0,0 }, + {1677,1677, 0, 0, 3493, 193,0 }, + {1678,1678, 0, 0, 1746, 73,0 }, + {1679,1679, 0, 0, 1013, 400,0 }, + {1680,1680, 0, 0, 3473, 1560,0 }, + {1681,1681, 0, 0, 1073, 40,0 }, + {1682,1682, 0, 0, 40000, 380,0 }, + {1683,1683, 0, 0, 1166, 400,0 }, + {1684,1684, 0, 0, 606, 146,0 }, + {1685,1685, 0, 0, 4553, 1486,0 }, + {1686,1686, 0, 0, 1126, 80,0 }, + {1687,1687, 0, 0, 40000, 73,0 }, + {1688,1688, 0, 0, 40000, 60,0 }, + {1689,1689, 0, 0, 40000, 66,0 }, + {1690,1690, 0, 0, 40000, 73,0 }, + {1691,1691, 0, 0, 40000, 73,0 }, + {1692,1692, 0, 0, 40000, 73,0 }, + {1693,1693, 0, 0, 40000, 73,0 }, + {1694,1694, 0, 0, 6380, 53,0 }, + {1695,1695, 0, 0, 6380, 60,0 }, + {1696,1696, 0, 0, 40000, 53,0 }, + {1697,1697, 0, 0, 40000, 0,0 }, + {1698,1698, 0, 0, 1880, 80,0 }, + {1699,1699, 0, 0, 40000, 60,0 }, + {1700,1700, 0, 0, 40000, 60,0 }, + {1701,1701, 0, 0, 1460, 80,0 }, + {1702,1702, 0, 0, 40000, 73,0 }, + {1703,1703, 0, 0, 40000, 0,0 }, + {1704,1704, 0, 0, 40000, 146,0 }, + {1705,1705, 0, 0, 40000, 66,0 }, + {1706,1706, 0, 0, 40000, 73,0 }, + {1707,1707, 0, 0, 40000, 160,0 }, + {1708,1708, 0, 0, 40000, 73,0 }, + {1709,1709, 0, 0, 40000, 193,0 }, + {1710,1710, 0, 0, 3740, 1260,0 }, + {1711,1711, 0, 0, 40000, 180,0 }, + {1712,1712, 0, 0, 40000, 173,0 }, + {1713,1713, 0, 0, 40000, 113,0 }, + {1714,1714, 0, 0, 40000, 86,0 }, + {1715,1715, 0, 0, 1853, 633,0 }, + {1716,1716, 0, 0, 40000, 0,0 }, + {1717,1717, 0, 0, 1066, 306,0 }, + {1718,1718, 0, 0, 40000, 86,0 }, + {1719,1719, 0, 0, 40000, 586,0 }, + {1720,1720, 0, 0, 40000, 86,0 }, + {1721,1721, 0, 0, 40000, 93,0 }, + {1722,1722, 0, 0, 40000, 373,0 }, + {1723,1723, 0, 0, 40000, 113,0 }, + {1724,1724, 0, 0, 40000, 353,0 }, + {1725,1725, 0, 0, 420, 73,0 }, + {1726,1726, 0, 0, 40000, 66,0 }, + {1727,1727, 0, 0, 40000, 53,0 }, + {1728,1728, 0, 0, 40000, 66,0 }, + {1729,1729, 0, 0, 40000, 100,0 }, + {1730,1730, 0, 0, 40000, 93,0 }, + {1731,1731, 0, 0, 40000, 0,0 }, + {1732,1732, 0, 0, 40000, 73,0 }, + {1733,1733, 0, 0, 40000, 80,0 }, + {1734,1734, 0, 0, 40000, 80,0 }, + {1735,1735, 0, 0, 40000, 80,0 }, + {1736,1736, 0, 0, 40000, 80,0 }, + {1737,1737, 0, 0, 40000, 80,0 }, + {1738,1738, 0, 0, 40000, 73,0 }, + {1739,1739, 0, 0, 40000, 73,0 }, + {1740,1740, 0, 0, 40000, 106,0 }, + {1741,1741, 0, 0, 40000, 73,0 }, + {1742,1742, 0, 0, 40000, 73,0 }, + {1743,1743, 0, 0, 40000, 80,0 }, + {1744,1744, 0, 0, 40000, 0,0 }, + {1745,1745, 0, 0, 40000, 80,0 }, + {1746,1746, 0, 0, 40000, 66,0 }, + {1747,1747, 0, 0, 40000, 73,0 }, + {1748,1748, 0, 0, 40000, 0,0 }, + {1749,1749, 0, 0, 40000, 80,0 }, + {1750,1750, 0, 0, 40000, 66,0 }, + {1751,1751, 0, 0, 40000, 73,0 }, + {1752,1752, 0, 0, 40000, 80,0 }, + {1753,1753, 0, 0, 40000, 33,0 }, + {1754,1754, 0, 0, 40000, 0,0 }, + {1755,1755, 0, 0, 40000, 266,0 }, + {1756,1756, 0, 0, 40000, 160,0 }, + {1757,1757, 0, 0, 40000, 93,0 }, + {1758,1758, 0, 0, 40000, 660,0 }, + {1759,1759, 0, 0, 40000, 1453,0 }, + {1760,1760, 0, 0, 40000, 660,0 }, + {1761,1761, 0, 0, 40000, 120,0 }, + {1762,1762, 0, 0, 40000, 140,0 }, + {1763,1763, 0, 0, 9820, 393,0 }, + {1764,1764, 0, 0, 40000, 73,0 }, + {1765,1765, 0, 0, 3620, 1166,0 }, + {1766,1766, 0, 0, 40000, 0,0 }, + {1767,1767, 0, 0, 40000, 0,0 }, + {1768,1768, 0, 0, 40000, 813,0 }, + {1769,1769, 0, 0, 40000, 0,0 }, + {1770,1770, 0, 0, 40000, 2386,0 }, + {1771,1771, 0, 0, 4380, 400,0 }, + {1772,1772, 0, 0, 853, 0,0 }, + {1773,1773, 0, 0, 3700, 93,0 }, + {1774,1774, 0, 0, 1580, 300,0 }, + {1775,1775, 0, 0, 453, 140,0 }, + {1776,1776, 0, 0, 40000, 66,0 }, + {1777,1777, 0, 0, 40000, 73,0 }, + {1778,1778, 0, 0, 40000, 206,0 }, + {1779,1779, 0, 0, 4646, 1560,0 }, + {1780,1780, 0, 0, 353, 146,0 }, + {1781,1781, 0, 0, 1300, 400,0 }, + {1782,1782, 0, 0, 4593, 1546,0 }, + {1783,1783, 0, 0, 613, 226,0 }, + {1784,1784, 0, 0, 626, 233,0 }, + {1785,1785, 0, 0, 3020, 66,0 }, + {1786,1786, 0, 0, 1093, 186,0 }, + {1787,1787, 0, 0, 6053, 1240,0 }, + {1788,1788, 0, 0, 633, 126,0 }, + {1789,1789, 0, 0, 40000, 66,0 }, + {1790,1790, 0, 0, 40000, 73,0 }, + {1791,1791, 0, 0, 40000, 1253,0 }, + {1792,1792, 0, 0, 626, 246,0 }, + {1793,1793, 48, 0, 293, 120,0 }, + {1794,1794, 48, 0, 100, 0,0 }, + {1795,1795, 60, 0, 240, 133,0 }, + {1796,1796, 60, 0, 160, 66,0 }, + {1797,1797, 70, 0, 140, 33,0 }, + {1798,1798, 51, 0, 526, 206,0 }, + {1799,1799, 60, 0, 173, 93,0 }, + {1798,1798, 54, 0, 520, 200,0 }, + {1800,1800, 60, 0, 153, 80,0 }, + {1798,1798, 56, 0, 520, 206,0 }, + {1801,1801, 60, 0, 673, 206,0 }, + {1798,1798, 61, 0, 506, 200,0 }, + {1798,1798, 63, 0, 513, 206,0 }, + {1802,1802, 48, 0, 673, 200,0 }, + {1798,1798, 68, 0, 440, 180,0 }, + {1803,1803, 60, 0, 1873, 653,0 }, + {1804,1804, 60, 0, 673, 200,0 }, + {1805,1805, 66, 0, 306, 120,0 }, + {1806,1806, 60, 0, 673, 200,0 }, + { 379, 379, 59, 0, 173, 93,0 }, + {1802,1802, 64, 0, 673, 206,0 }, + {1807,1807, 48, 0, 1006, 20,0 }, + {1808,1808, 56, 0, 120, 40,0 }, + {1809,1809, 53, 0, 286, 133,0 }, + {1810,1810, 65, 0, 106, 0,0 }, + {1811,1811, 49, 0, 293, 133,0 }, + {1811,1811, 43, 0, 293, 133,0 }, + { 386, 386, 65, 0, 1013, 673,0 }, + { 386, 386, 60, 0, 1000, 660,0 }, + {1812,1812, 70, 0, 260, 113,0 }, + {1812,1812, 65, 0, 306, 120,0 }, + {1813,1813, 60, 0, 246, 106,0 }, + {1814,1814, 60, 0, 193, 120,0 }, + {1815,1815, 56, 0, 206, 13,0 }, + {1816,1816, 53, 0, 433, 73,0 }, + {1817,1817, 60, 0, 220, 113,0 }, + {1818,1818, 48, 0, 300, 66,0 }, + {1819,1819, 69, 0, 126, 0,0 }, + { 328, 328, 67, 0, 140, 93,0 }, + { 328, 328, 62, 0, 153, 100,0 }, + {1820,1820, 65, 0, 433, 100,0 }, + {1821,1821, 60, 0, 426, 100,0 }, + {1822,1822, 63, 0, 113, 46,0 }, + {1823,1823, 63, 0, 1866, 653,0 }, + {1824,1824, 67, 0, 273, 60,0 }, + {1825,1825, 60, 0, 973, 360,0 }, + {1825,1825, 72, 0, 806, 273,0 }, + { 401, 401, 62, 0, 46, 0,0 }, + {1826,1826, 48, 0, 126, 66,0 }, + {1827,1827, 53, 0, 980, 353,0 }, + {1828,1828, 60, 0, 293, 133,0 }, + {1829,1829, 60, 0, 160, 20,0 }, + {1830,1830, 60, 0, 126, 86,0 }, + {1831,1831, 60, 0, 173, 93,0 }, + {1832,1832, 0, 0, 40000, 106,0 }, + {1833,1833, 0, 0, 3780, 73,0 }, + {1834,1834, 0, 0, 3820, 1666,0 }, + {1835,1835, 0, 0, 40000, 73,0 }, + {1836,1836, 0, 0, 40000, 333,0 }, + {1837,1837, 0, 0, 40000, 220,0 }, + {1838,1838, 0, 0, 40000, 0,0 }, + {1839,1839, 0, 0, 40000, 53,0 }, + {1840,1840, 0, 0, 40000, 60,0 }, + {1841,1841, 0, 0, 5913, 2306,0 }, + {1842,1842, 0, 0, 7713, 2466,0 }, + { 525, 525, 0, 0, 4660, 660,0 }, + {1843,1843, 0, 0, 40000, 313,0 }, + {1844,1844, 0, 0, 40000, 0,0 }, + {1845,1845, 0, 0, 40000, 0,0 }, + {1846,1846, 0, 0, 1246, 453,0 }, + {1847,1847, 0, 0, 9600, 1580,0 }, + {1848,1848, 0, 0, 40000, 106,0 }, + {1849,1849, 0, 0, 2040, 400,0 }, + {1850,1850, 0, 0, 40000, 73,0 }, + {1851,1851, 0, 0, 4220, 620,0 }, + {1852,1852, 0, 0, 40000, 0,0 }, + {1853,1853, 0, 0, 40000, 433,0 }, + {1854,1854, 0, 0, 40000, 66,0 }, + {1855,1855, 0, 0, 40000, 46,0 }, + {1856,1856, 0, 0, 40000, 240,0 }, + {1857,1857, 0, 0, 40000, 313,0 }, + {1858,1858, 0, 0, 40000, 26,0 }, + {1859,1859, 0, 0, 40000, 0,0 }, + {1860,1860, 0, 0, 40000, 73,0 }, + {1861,1861, 0, 0, 6940, 66,0 }, + {1862,1862, 0, 0, 40000, 0,0 }, + {1863,1863, 0, 0, 40000, 60,0 }, + {1864,1864, 0, 0, 8140, 1440,0 }, + {1865,1865, 0, 0, 40000, 0,0 }, + {1866,1866, 0, 0, 40000, 613,0 }, + {1867,1867, 0, 0, 40000, 0,0 }, + {1868,1868, 0, 0, 633, 233,0 }, + {1869,1869, 0, 0, 40000, 226,0 }, + {1870,1870, 0, 0, 2280, 746,0 }, + {1871,1871, 0, 0, 1940, 633,0 }, + {1872,1872, 0, 0, 4220, 620,0 }, + {1873,1873, 0, 0, 40000, 133,0 }, + {1874,1874, 41, 0, 380, 153,0 }, + {1875,1875, 70, 0, 106, 0,0 }, + {1876,1876, 60, 0, 380, 206,0 }, + {1877,1877, 80, 0, 100, 0,0 }, + {1878,1878, 84, 0, 120, 0,0 }, + {1879,1879, 72, 0, 500, 433,0 }, + {1880,1880, 84, 0, 860, 553,0 }, + { 128, 128, 70, 0, 106, 0,0 }, + { 132, 132, 60, 0, 146, 86,0 }, + {1881,1882, 0, 4, 40000, 260,0 }, + {1883,1883, 0, 0, 40000, 0,0 }, + {1884,1885, 0, 4, 40000, 73,0 }, + {1886,1887, 0, 4, 40000, 86,0 }, + {1888,1889, 0, 4, 40000, 73,0 }, + {1890,1890, 0, 0, 40000, 300,0 }, + {1891,1891, 0, 0, 40000, 693,0 }, + {1892,1892, 0, 0, 40000, 586,0 }, + {1893,1893, 0, 0, 40000, 286,0 }, + {1894,1894, 0, 0, 1620, 773,0 }, + {1895,1895, 0, 0, 40000, 0,0 }, + {1896,1896, 0, 0, 40000, 193,0 }, + {1897,1897, 0, 0, 1873, 820,0 }, + {1898,1898, 0, 0, 4520, 753,0 }, + {1899,1899, 0, 0, 40000, 0,0 }, + {1900,1900, 0, 0, 40000, 220,0 }, + {1901,1901, 0, 0, 40000, 133,0 }, + {1902,1902, 0, 0, 40000, 73,0 }, + {1903,1903, 0, 0, 40000, 0,0 }, + {1904,1904, 0, 0, 7326, 2420,0 }, + {1905,1905, 0, 0, 1186, 446,0 }, + {1906,1906, 0, 0, 40000, 553,0 }, + {1907,1907, 0, 0, 40000, 293,0 }, + {1908,1908, 0, 0, 40000, 586,0 }, + {1909,1909, 0, 0, 2326, 793,0 }, + { 501, 501, 0, 0, 480, 226,0 }, + {1910,1910, 0, 0, 40000, 93,0 }, + {1911,1911, 0, 0, 620, 226,0 }, + {1912,1912, 0, 0, 2373, 800,0 }, + {1913,1913, 0, 0, 40000, 4986,0 }, + {1914,1914, 0, 0, 626, 240,0 }, + { 511, 511, 0, 0, 2326, 800,0 }, + {1915,1915, 0, 0, 340, 146,0 }, + {1910,1910, 60, 0, 40000, 93,0 }, + { 511, 511, 72, 0, 1566, 546,0 }, + {1915,1915, 84, 0, 246, 120,0 }, + {1916,1916, 0, 0, 40000, 0,0 }, + {1917,1917, 0, 0, 2713, 666,0 }, + {1918,1918, 0, 0, 40000, 0,0 }, + {1919,1919, 0, 0, 40000, 46,0 }, + {1920,1920, 0, 0, 40000, 0,0 }, + {1921,1921, 0, 0, 40000, 53,0 }, + {1922,1922, 0, 0, 40000, 33,0 }, + {1923,1923, 0, 0, 2073, 193,0 }, + {1924,1924, 0, 0, 40000, 146,0 }, + {1925,1925, 0, 0, 40000, 100,0 }, + {1926,1926, 0, 0, 40000, 93,0 }, + {1927,1927, 0, 0, 40000, 73,0 }, + {1928,1928, 0, 0, 40000, 540,0 }, + {1929,1929, 0, 0, 40000, 520,0 }, + {1930,1930, 0, 0, 40000, 506,0 }, + {1931,1931, 0, 0, 7406, 200,0 }, + {1932,1932, 0, 0, 5906, 133,0 }, + {1933,1933, 0, 0, 7426, 240,0 }, + {1934,1934, 0, 0, 7426, 240,0 }, + {1935,1935, 0, 0, 40000, 66,0 }, + {1936,1936, 0, 0, 40000, 66,0 }, + {1937,1937, 0, 0, 40000, 53,0 }, + {1938,1938, 0, 0, 40000, 66,0 }, + {1939,1939, 0, 0, 40000, 66,0 }, + {1940,1940, 0, 0, 40000, 53,0 }, + {1941,1941, 0, 0, 40000, 2146,0 }, + {1942,1942, 0, 0, 40000, 1126,0 }, + {1943,1943, 0, 0, 40000, 1020,0 }, + {1944,1944, 0, 0, 40000, 433,0 }, + {1945,1945, 0, 0, 40000, 0,0 }, + {1946,1946, 0, 0, 40000, 140,0 }, + {1947,1947, 0, 0, 4660, 660,0 }, + {1948,1948, 0, 0, 40000, 66,0 }, + {1949,1949, 0, 0, 40000, 4193,0 }, + {1950,1950, 0, 0, 7713, 2466,0 }, + {1951,1951, 0, 0, 40000, 73,0 }, + {1952,1952, 0, 0, 8100, 2093,0 }, + {1953,1953, 0, 0, 40000, 86,0 }, + {1954,1954, 0, 0, 40000, 80,0 }, + {1955,1955, 0, 0, 4113, 1526,0 }, + {1956,1956, 0, 0, 40000, 66,0 }, + {1957,1957, 0, 0, 40000, 100,0 }, + {1958,1958, 0, 0, 40000, 213,0 }, + {1959,1959, 0, 0, 40000, 100,0 }, + {1960,1960, 0, 0, 1186, 100,0 }, + {1961,1961, 0, 0, 40000, 433,0 }, + {1962,1962, 0, 0, 40000, 146,0 }, + {1963,1963, 0, 0, 40000, 400,0 }, + {1964,1964, 0, 0, 40000, 66,0 }, + {1965,1965, 0, 0, 40000, 193,0 }, + {1966,1966, 0, 0, 1153, 100,0 }, + {1967,1967, 0, 0, 4800, 1400,0 }, + {1968,1968, 0, 0, 2906, 713,0 }, + {1969,1969, 0, 0, 40000, 73,0 }, + {1970,1970, 0, 0, 2280, 746,0 }, + {1971,1971, 0, 0, 40000, 66,0 }, + {1972,1972, 0, 0, 40000, 86,0 }, + {1973,1973, 0, 0, 40000, 86,0 }, + {1974,1974, 0, 0, 40000, 66,0 }, + {1975,1975, 0, 0, 40000, 66,0 }, + {1976,1976, 0, 0, 40000, 66,0 }, + {1977,1977, 0, 0, 40000, 46,0 }, + {1978,1978, 0, 0, 40000, 73,0 }, + {1979,1979, 0, 0, 40000, 73,0 }, + {1980,1980, 0, 0, 40000, 66,0 }, + {1981,1981, 0, 0, 40000, 66,0 }, + {1982,1982, 0, 0, 40000, 66,0 }, + {1983,1983, 0, 0, 40000, 73,0 }, + {1984,1984, 0, 0, 40000, 73,0 }, + {1985,1985, 0, 0, 40000, 253,0 }, + {1986,1986, 0, 0, 40000, 126,0 }, + {1987,1987, 0, 0, 40000, 126,0 }, + {1988,1988, 0, 0, 40000, 66,0 }, + {1989,1989, 0, 0, 40000, 66,0 }, + {1990,1990, 0, 0, 40000, 53,0 }, + {1991,1991, 0, 0, 40000, 140,0 }, + {1992,1992, 0, 0, 40000, 40,0 }, + {1993,1993, 0, 0, 40000, 73,0 }, + {1994,1994, 0, 0, 40000, 66,0 }, + {1995,1995, 0, 0, 40000, 73,0 }, + {1996,1996, 0, 0, 40000, 73,0 }, + {1997,1997, 0, 0, 40000, 73,0 }, + {1998,1998, 0, 0, 40000, 73,0 }, + {1999,1999, 0, 0, 40000, 66,0 }, + {2000,2000, 0, 0, 40000, 433,0 }, + {2001,2001, 0, 0, 40000, 433,0 }, + {2002,2002, 0, 0, 2440, 706,0 }, + {2003,2003, 0, 0, 13960, 4800,0 }, + {2004,2004, 0, 0, 7393, 2480,0 }, + {2005,2005, 0, 0, 7220, 2073,0 }, + {2006,2006, 0, 0, 633, 233,0 }, + {2007,2007, 0, 0, 2326, 780,0 }, + {2008,2008, 0, 0, 40000, 73,0 }, + {2009,2009, 0, 0, 40000, 106,0 }, + {2010,2010, 0, 0, 40000, 126,0 }, + {2011,2011, 0, 0, 40000, 386,0 }, + {2012,2012, 0, 0, 40000, 66,0 }, + {2013,2013, 0, 0, 6893, 1273,0 }, + {2014,2014, 0, 0, 2546, 633,0 }, + {2015,2015, 0, 0, 206, 106,0 }, + {2016,2016, 0, 0, 213, 113,0 }, + {2017,2017, 0, 0, 360, 140,0 }, + {2018,2018, 0, 0, 1013, 193,0 }, + {2019,2019, 0, 0, 266, 66,0 }, + {2020,2020, 0, 0, 1880, 660,0 }, + {2021,2021, 0, 0, 286, 206,0 }, + {2022,2022, 0, 0, 3706, 1353,0 }, + {2023,2023, 0, 0, 1106, 380,0 }, + {2024,2024, 0, 0, 13220, 2466,0 }, + {2025,2025, 0, 0, 333, 26,0 }, + {2026,2026, 0, 0, 7346, 2440,0 }, + {2027,2027, 0, 0, 1273, 453,0 }, + { 352, 352, 51, 2, 6, 0,0 }, + {2028,2028, 35, 0, 700, 253,0 }, + {2028,2028, 36, 0, 706, 266,0 }, + {2029,2029, 47, 0, 100, 0,0 }, + {2030,2030, 38, 0, 346, 140,0 }, + {2019,2019, 39, 0, 220, 106,0 }, + {2031,2031, 45, 0, 286, 133,0 }, + { 492, 492, 41, 0, 1040, 406,0 }, + {2032,2032, 42, 0, 220, 106,0 }, + {2033,2033, 44, 0, 500, 193,0 }, + { 492, 492, 48, 0, 833, 346,0 }, + {2034,2034, 46, 0, 1866, 646,0 }, + { 492, 492, 53, 0, 873, 386,0 }, + { 167, 167, 56, 0, 646, 353,0 }, + {2035,2035, 61, 0, 366, 146,0 }, + {2036,2036, 56, 0, 1346, 473,0 }, + {2037,2037, 60, 0, 213, 126,0 }, + { 144, 144, 59, 0, 213, 0,0 }, + {2038,2038, 59, 0, 106, 0,0 }, + { 169, 169, 51, 0, 380, 366,0 }, + { 169, 169, 45, 0, 380, 366,0 }, + {2039,2039, 72, 0, 246, 20,0 }, + {2040,2040, 60, 0, 280, 20,0 }, + {2041,2041, 58, 0, 373, 360,0 }, + {2042,2042, 53, 0, 380, 366,0 }, + {2043,2043, 73, 0, 120, 26,0 }, + { 158, 158, 75, 0, 126, 140,0 }, + {2044,2044, 0, 0, 6786, 1073,0 }, + {2045,2045, 0, 0, 2046, 473,0 }, + {2046,2046, 0, 0, 3746, 1273,0 }, + {2047,2047, 0, 0, 1200, 3086,0 }, + {2048,2048, 0, 0, 1200, 3080,0 }, + {2049,2049, 0, 0, 40000, 2453,0 }, + {2050,2050, 0, 0, 40000, 413,0 }, + {2051,2051, 0, 0, 980, 2553,0 }, + {2052,2052, 0, 0, 40000, 2420,0 }, + {2053,2053, 0, 0, 40000, 2506,0 }, + {2054,2054, 0, 0, 40000, 380,0 }, + {2055,2055, 0, 0, 40000, 660,0 }, + {2056,2056, 0, 0, 40000, 73,0 }, + {2057,2057, 0, 0, 40000, 333,0 }, + {2058,2058, 0, 0, 833, 146,0 }, + {2059,2059, 0, 0, 1686, 620,0 }, + {2060,2060, 0, 0, 40000, 73,0 }, + {2061,2061, 0, 0, 40000, 0,0 }, + {2062,2062, 0, 0, 1873, 633,0 }, + {2063,2063, 0, 0, 40000, 380,0 }, + {2064,2064, 0, 0, 366, 286,0 }, + {2065,2065, 0, 0, 8866, 1366,0 }, + {2066,2066, 0, 0, 40000, 1513,0 }, + {2067,2067, 0, 0, 40000, 333,0 }, + {2068,2068, 0, 0, 9600, 1573,0 }, + {2069,2069, 0, 0, 3293, 746,0 }, + {2070,2070, 0, 0, 40000, 53,0 }, + {2071,2071, 0, 0, 40000, 73,0 }, + {2072,2072, 0, 0, 40000, 73,0 }, + {2073,2073, 0, 0, 40000, 240,0 }, + {2074,2074, 0, 0, 40000, 240,0 }, + {2075,2075, 0, 0, 40000, 140,0 }, + {2076,2076, 0, 0, 40000, 113,0 }, + {2077,2077, 0, 0, 40000, 240,0 }, + {2078,2078, 0, 0, 3613, 1146,0 }, + {2079,2079, 0, 0, 40000, 126,0 }, + {2080,2080, 0, 0, 40000, 0,0 }, + {2081,2081, 0, 0, 40000, 633,0 }, + {2082,2082, 0, 0, 40000, 453,0 }, + {2083,2083, 0, 0, 40000, 1146,0 }, + {2084,2084, 0, 0, 40000, 3600,0 }, + {2085,2085, 0, 0, 40000, 1586,0 }, + {2086,2086, 0, 0, 40000, 1586,0 }, + {2087,2087, 0, 0, 40000, 1586,0 }, + {2088,2088, 0, 0, 40000, 1646,0 }, + {2089,2089, 0, 0, 40000, 1580,0 }, + {2090,2090, 0, 0, 40000, 4393,0 }, + {2091,2091, 0, 0, 40000, 4540,0 }, + {2092,2092, 0, 0, 21373, 6160,0 }, + {2093,2093, 0, 0, 40000, 633,0 }, + {2094,2094, 0, 0, 18420, 6146,0 }, + {2095,2095, 0, 0, 2306, 813,0 }, + {2096,2096, 0, 0, 2813, 333,0 }, + {2097,2097, 0, 0, 3106, 600,0 }, + {2098,2098, 0, 0, 1026, 1580,0 }, + {2099,2099, 0, 0, 1873, 346,0 }, + {2100,2100, 0, 0, 40000, 73,0 }, + {2101,2101, 0, 0, 40000, 73,0 }, + {2102,2102, 0, 0, 1200, 1906,0 }, + {2103,2103, 0, 0, 980, 1313,0 }, + {2104,2104, 0, 0, 200, 20,0 }, + {2105,2105, 0, 0, 640, 253,0 }, + {2106,2106, 0, 0, 3120, 240,0 }, + {2107,2107, 0, 0, 753, 146,0 }, + {2108,2108, 0, 0, 40000, 3060,0 }, + {2109,2109, 0, 0, 40000, 233,0 }, + {2110,2110, 0, 0, 40000, 246,0 }, + {2111,2111, 0, 0, 40000, 240,0 }, + { 752, 752, 60, 0, 173, 20,0 }, + { 755, 755, 12, 0, 626, 240,0 }, + {2112,2112, 89, 0, 113, 0,0 }, + {2113,2113, 89, 0, 700, 266,0 }, + { 755, 755, 14, 0, 626, 240,0 }, + { 755, 755, 16, 0, 626, 246,0 }, + {2114,2114, 84, 0, 1593, 553,0 }, + { 755, 755, 19, 0, 626, 240,0 }, + {2115,2115, 38, 0, 220, 166,0 }, + {2116,2116, 36, 0, 1686, 760,0 }, + { 755, 755, 28, 0, 626, 240,0 }, + { 755, 755, 26, 0, 626, 240,0 }, + { 755, 755, 35, 0, 633, 246,0 }, + { 755, 755, 30, 0, 626, 240,0 }, + {2117,2117, 60, 0, 180, 53,0 }, + {2104,2104, 60, 0, 173, 20,0 }, + {2104,2104, 55, 0, 173, 20,0 }, + { 730, 730, 94, 0, 1886, 660,0 }, + {2118,2118, 0, 0, 1226, 73,0 }, + {2119,2119, 0, 0, 40000, 0,0 }, + {2120,2120, 0, 0, 40000, 146,0 }, + {2121,2121, 0, 0, 40000, 80,0 }, + {2122,2122, 0, 0, 40000, 80,0 }, + {2123,2123, 0, 0, 40000, 0,0 }, + {2124,2124, 0, 0, 40000, 126,0 }, + {2125,2125, 0, 0, 40000, 213,0 }, + {2126,2126, 0, 0, 40000, 80,0 }, + {2127,2127, 0, 0, 40000, 73,0 }, + {2128,2128, 0, 0, 40000, 73,0 }, + {2129,2129, 0, 0, 40000, 73,0 }, + {2130,2130, 0, 0, 40000, 80,0 }, + {2131,2131, 0, 0, 40000, 73,0 }, + {2132,2132, 0, 0, 40000, 73,0 }, + {2133,2133, 0, 0, 40000, 66,0 }, + {2134,2134, 0, 0, 40000, 186,0 }, + {2135,2135, 0, 0, 9966, 426,0 }, + {2136,2136, 0, 0, 40000, 400,0 }, + {2137,2137, 0, 0, 40000, 326,0 }, + {2138,2138, 0, 0, 386, 80,0 }, + {2139,2139, 0, 0, 40000, 246,0 }, + {2140,2140, 0, 0, 3473, 73,0 }, + {2141,2141, 60, 0, 160, 66,0 }, + {2141,2141, 44, 0, 160, 60,0 }, + {2142,2142, 47, 0, 173, 93,0 }, + {2143,2143, 47, 0, 186, 80,0 }, + {2144,2144, 62, 0, 1933, 93,0 }, + {2145,2145, 93, 0, 1146, 473,0 }, + {2146,2146, 50, 0, 286, 93,0 }, + {2145,2145, 40, 0, 2013, 840,0 }, + {2147,2147, 60, 0, 106, 73,0 }, + { 898, 898, 60, 0, 173, 133,0 }, + {2147,2147, 57, 0, 106, 73,0 }, + { 900, 900, 42, 0, 620, 240,0 }, + { 900, 900, 38, 0, 626, 240,0 }, + { 908, 908, 88, 0, 160, 26,0 }, + {2148,2148, 0, 0, 9440, 140,0 }, + {2149,2149, 0, 0, 40000, 73,0 }, + {2150,2150, 0, 0, 4613, 420,0 }, + {2151,2151, 0, 0, 40000, 86,0 }, + {2152,2152, 0, 0, 40000, 406,0 }, + {2153,2153, 0, 0, 40000, 440,0 }, + {2154,2154, 0, 0, 4340, 133,0 }, + {2155,2155, 0, 0, 4460, 706,0 }, + {2156,2156, 0, 0, 40000, 73,0 }, + {2157,2157, 0, 0, 4660, 1573,0 }, + {2158,2158, 0, 0, 966, 333,0 }, + {2159,2159, 0, 0, 1933, 640,0 }, + { 136, 136, 0, 0, 2326, 786,0 }, + { 168, 168, 0, 0, 286, 366,0 }, + { 164, 164, 0, 0, 7373, 2460,0 }, + { 167, 167, 0, 0, 793, 426,0 }, + {2160,2160, 65, 0, 166, 73,0 }, + {2161,2161, 21, 0, 480, 146,0 }, + {2162, 173, 0, 4, 4220, 80,0 }, + {2163,2164, 0, 4, 4640, 3066,0 }, + {2165,2166, 0, 4, 7273, 3920,0 }, + {2167,2168, 0, 4, 3766, 1253,0 }, + {2169,2170, 0, 4, 6266, 2400,0 }, + {2171,2172, 0, 4, 18213, 0,0 }, + {2173,2174, 0, 4, 40000, 713,0 }, + {2175,2174, 0, 4, 40000, 733,0 }, + {2176, 299, 0, 4, 40000, 273,0 }, + {2177,2178, 0, 4, 40000, 66,0 }, + {2179,2180, 0, 4, 40000, 393,0 }, + {2181,2182, 0, 4, 40000, 413,0 }, + {2183,2184, 0, 4, 7406, 200,0 }, + { 127, 127, 65, 0, 226, 120,0 }, + { 127, 127, 72, 0, 180, 100,0 }, + { 364, 365, 52, 4, 120, 0,0 }, + {2185,2186, 60, 4, 173, 0,0 }, + {1550,1551, 47, 4, 520, 0,0 }, + {1556,1557, 76, 4, 833, 0,0 }, + { 374, 375, 84, 4, 813, 0,0 }, + {1564,1565, 83, 4, 220, 0,0 }, + {1568,1569, 24, 4, 1840, 620,0 }, + {1556,1557, 77, 4, 820, 300,0 }, + {1572,1573, 60, 4, 286, 0,0 }, + {1574,1575, 65, 4, 293, 0,0 }, + { 391, 392, 44, 4, 160, 53,0 }, + { 391, 393, 40, 4, 460, 66,0 }, + {1606,1607, 72, 4, 120, 73,0 }, + { 398, 399, 73, 4, 1293, 173,0 }, + {1608,1609, 70, 4, 1580, 0,0 }, + {2187,2187, 0, 0, 40000, 353,0 }, + {2188,2188, 0, 0, 40000, 333,0 }, + {2189,2189, 0, 0, 5913, 2306,0 }, + {2190,2190, 0, 0, 7720, 1260,0 }, + {2191,2191, 0, 0, 213, 6420,0 }, + {2192,2192, 0, 0, 40000, 380,0 }, + {2193,2193, 0, 0, 1153, 760,0 }, + {2194,2194, 0, 0, 40000, 66,0 }, + {2195,2195, 0, 0, 4440, 66,0 }, + {2196,2196, 0, 0, 40000, 73,0 }, + {2197,2197, 0, 0, 40000, 53,0 }, + {2198,2198, 0, 0, 40000, 60,0 }, + {2199,2199, 0, 0, 40000, 60,0 }, + {2200,2200, 0, 0, 8133, 1433,0 }, + { 528, 528, 0, 0, 966, 346,0 }, + {2201,2201, 0, 0, 40000, 126,0 }, + {2202,2202, 0, 0, 286, 1293,0 }, + {2203,2203, 0, 0, 40000, 0,0 }, + {2204,2204, 41, 0, 246, 20,0 }, + {2205,2205, 84, 0, 160, 26,0 }, + {2206,2206, 72, 0, 440, 180,0 }, + { 741, 741, 48, 0, 220, 26,0 }, + {2207,2207, 0, 0, 2126, 173,0 }, + {2208,2208, 0, 0, 40000, 0,0 }, + {2209,2209, 0, 0, 40000, 380,0 }, + {2210,2210, 0, 0, 4553, 1486,0 }, + {2211,2211, 0, 0, 40000, 73,0 }, + {2212,2212, 0, 0, 40000, 73,0 }, + {2213,2213, 0, 0, 1460, 80,0 }, + {2214,2214, 0, 0, 40000, 66,0 }, + {2215,2215, 0, 0, 40000, 186,0 }, + {2216,2216, 0, 0, 40000, 180,0 }, + {2217,2217, 0, 0, 40000, 173,0 }, + {2218,2218, 0, 0, 40000, 113,0 }, + {2219,2219, 0, 0, 40000, 86,0 }, + {2220,2220, 0, 0, 40000, 373,0 }, + {2221,2221, 0, 0, 40000, 113,0 }, + {2222,2222, 0, 0, 40000, 353,0 }, + {2223,2223, 0, 0, 40000, 66,0 }, + {2224,2224, 0, 0, 40000, 53,0 }, + {2225,2225, 0, 0, 40000, 66,0 }, + {2226,2226, 0, 0, 40000, 100,0 }, + {2227,2227, 0, 0, 40000, 73,0 }, + {2228,2228, 0, 0, 40000, 73,0 }, + {2229,2229, 0, 0, 40000, 66,0 }, + {2230,2230, 0, 0, 40000, 66,0 }, + {2231,2231, 0, 0, 40000, 80,0 }, + {2232,2232, 0, 0, 40000, 66,0 }, + {2233,2233, 0, 0, 40000, 80,0 }, + {2234,2234, 0, 0, 40000, 660,0 }, + {2235,2235, 0, 0, 40000, 120,0 }, + {2236,2236, 0, 0, 9820, 393,0 }, + {2237,2237, 0, 0, 40000, 73,0 }, + {2238,2238, 0, 0, 3620, 1166,0 }, + {2239,2239, 0, 0, 40000, 0,0 }, + {2240,2240, 0, 0, 40000, 0,0 }, + {2241,2241, 0, 0, 3020, 66,0 }, + {2242,2242, 0, 0, 6053, 1240,0 }, + {2243,2243, 0, 0, 633, 126,0 }, + {2244,2244, 0, 0, 40000, 66,0 }, + {2245,2245, 0, 0, 40000, 73,0 }, + {2246,2246, 0, 0, 626, 246,0 }, + {2247,2247, 60, 0, 173, 93,0 }, + {2248,2248, 60, 0, 673, 206,0 }, + {2249,2249, 48, 0, 673, 200,0 }, + {2250,2250, 60, 0, 1873, 653,0 }, + {2251,2251, 60, 0, 673, 200,0 }, + {2252,2252, 66, 0, 306, 120,0 }, + {2253,2253, 60, 0, 673, 200,0 }, + {2249,2249, 64, 0, 673, 206,0 }, + {2254,2254, 60, 0, 246, 106,0 }, + {2255,2255, 60, 0, 193, 120,0 }, + {2256,2256, 56, 0, 206, 13,0 }, + {2257,2257, 53, 0, 433, 73,0 }, + {2258,2258, 60, 0, 220, 113,0 }, + {2259,2259, 48, 0, 300, 66,0 }, + {2260,2260, 67, 0, 273, 60,0 }, + {2261,2261, 60, 0, 973, 360,0 }, + {2261,2261, 72, 0, 806, 273,0 }, + {2262,2262, 60, 0, 173, 93,0 }, + {2263,2263, 0, 0, 2493, 866,0 }, + {2264,2264, 24, 0, 173, 93,0 }, + {2265,2265, 36, 0, 140, 0,0 }, + { 343, 343, 36, 0, 146, 80,0 }, + { 347, 347, 0, 0, 353, 133,0 }, + { 347, 347, 12, 0, 420, 146,0 }, + {2266,2266, 12, 0, 346, 100,0 }, + {2267,2267, 24, 0, 106, 46,0 }, + {2267,2267, 36, 0, 100, 0,0 }, + {2268,2268, 0, 0, 1006, 293,0 }, + {2266,2266, 24, 0, 293, 93,0 }, + {2269,2269, 88, 0, 1106, 120,0 }, + {2270,2270, 88, 0, 666, 120,0 }, + {2271,2271, 13, 0, 760, 360,0 }, + { 351, 351, 0, 0, 966, 346,0 }, + {2271,2271, 15, 0, 760, 420,0 }, + {2272,2272, 0, 0, 4513, 640,0 }, + {2273,2273, 0, 0, 15486, 1580,0 }, + {2274,2274, 0, 0, 6940, 66,0 }, + {2275,2275, 0, 0, 6866, 2380,0 }, + {2276,2276, 0, 0, 7613, 1566,0 }, + {2277,2277, 0, 0, 1186, 420,0 }, + {2278,2278, 0, 0, 1166, 400,0 }, + {2279,2279, 0, 0, 40000, 2940,0 }, + {2280,2280, 0, 0, 40000, 0,0 }, + {2281,2281, 0, 0, 18226, 786,0 }, + {2282,2282, 0, 0, 40000, 0,0 }, + {2283,2283, 0, 0, 713, 200,0 }, + {2284,2284, 0, 0, 40000, 126,0 }, + {2285,2285, 0, 0, 40000, 353,0 }, + {2286,2286, 0, 0, 40000, 333,0 }, + {2287,2287, 0, 0, 40000, 0,0 }, + {2288,2288, 0, 0, 40000, 0,0 }, + {2289,2289, 0, 0, 40000, 0,0 }, + {2290,2290, 0, 0, 40000, 0,0 }, + {2291,2291, 0, 0, 40000, 73,0 }, + {2292,2292, 0, 0, 40000, 66,0 }, + {2293,2293, 0, 0, 15893, 153,0 }, + {2294,2294, 0, 0, 40000, 253,0 }, + {2295,2295, 0, 0, 2813, 333,0 }, + {2296,2296, 0, 0, 40000, 3920,0 }, + {2297,2297, 79, 0, 113, 0,0 }, + {2297,2297, 72, 0, 126, 140,0 }, + {2298,2298, 72, 0, 100, 26,0 }, + {2298,2298, 79, 0, 100, 0,0 }, + { 554, 554, 60, 0, 400, 126,0 }, + {2299,2299, 72, 0, 793, 173,0 }, + {2300,2300, 84, 0, 226, 66,0 }, + { 555, 555, 66, 0, 113, 0,0 }, + {2301,2302, 35, 4, 2333, 800,0 }, + {2303,2304, 52, 4, 120, 0,0 }, + {2305,1548, 48, 4, 173, 0,0 }, + {1595,1595, 58, 0, 146, 166,0 }, + {2305,1548, 60, 4, 173, 0,0 }, + {2306,2307, 47, 4, 1893, 700,0 }, + {2306,2307, 43, 4, 1953, 740,0 }, + {2306,2307, 49, 4, 1880, 686,0 }, + {2306,2307, 51, 4, 1886, 706,0 }, + {2306,2307, 54, 4, 1906, 720,0 }, + {2306,2307, 57, 4, 1900, 720,0 }, + {2306,2307, 72, 4, 1593, 606,0 }, + {2306,2307, 60, 4, 1900, 720,0 }, + {2306,2307, 76, 4, 1593, 606,0 }, + {2306,2307, 84, 4, 1593, 613,0 }, + {2306,2307, 36, 4, 2386, 920,0 }, + {1560,2308, 65, 4, 293, 213,0 }, + {2309,2310, 84, 4, 1373, 306,0 }, + {1564,1564, 83, 0, 220, 113,0 }, + { 380, 381, 84, 4, 1593, 566,0 }, + {1568,1568, 24, 0, 1833, 613,0 }, + {2306,2307, 77, 4, 1593, 606,0 }, + {2311,2312, 60, 4, 286, 0,0 }, + {2313,2314, 65, 4, 513, 0,0 }, + {2315,2315, 59, 0, 106, 0,0 }, + {2316,2316, 51, 0, 386, 373,0 }, + {1612,1612, 45, 0, 393, 380,0 }, + {2317,2317, 71, 0, 446, 180,0 }, + {2318,2318, 60, 0, 280, 20,0 }, + {2319,2319, 58, 0, 393, 373,0 }, + {2320,2320, 53, 0, 393, 380,0 }, + { 397, 397, 64, 0, 220, 86,0 }, + {2321,2321, 71, 0, 106, 46,0 }, + {2322,2322, 61, 0, 986, 340,0 }, + {2323,2323, 61, 0, 1893, 633,0 }, + {2324, 392, 44, 4, 166, 46,0 }, + {2324, 393, 40, 4, 460, 60,0 }, + {1595,1595, 69, 0, 126, 140,0 }, + {1595,1595, 68, 0, 126, 140,0 }, + {1595,1595, 63, 0, 146, 166,0 }, + {2325,2326, 74, 4, 380, 106,0 }, + {2327,2328, 60, 4, 1026, 333,0 }, + {2329,2330, 80, 4, 40000, 0,0 }, + {2331,2332, 64, 4, 1900, 640,0 }, + { 397, 397, 72, 0, 193, 80,0 }, + {2333,2334, 78, 4, 820, 0,0 }, + {1608,1609, 82, 4, 1580, 0,0 }, + {2315,2315, 48, 0, 106, 0,0 }, + {2316,2316, 53, 0, 386, 373,0 }, + {2335,2335, 0, 0, 3586, 1133,0 }, + {2336,2337, 0, 4, 1186, 420,0 }, + {2338,2339, 0, 4, 40000, 320,0 }, + {2340,2340, 0, 0, 8826, 1346,0 }, + {2341,2341, 0, 0, 3440, 753,0 }, + {2342,2342, 0, 0, 40000, 360,0 }, + {2343,2343, 0, 0, 40000, 413,0 }, + {2344,2345, 0, 4, 40000, 60,0 }, + {2346,2346, 0, 0, 40000, 60,0 }, + {2347,2348, 0, 4, 40000, 126,0 }, + {2349,2350, 0, 4, 40000, 73,0 }, + {2351,2352, 0, 4, 40000, 73,0 }, + {2353,2354, 0, 4, 40000, 86,0 }, + {2355,2356, 0, 4, 40000, 453,0 }, + {2357,2357, 14, 0, 186, 20,0 }, + {2358,2358, 35, 0, 246, 73,0 }, + {2357,2357, 19, 0, 166, 26,0 }, + {2359,2359, 43, 0, 286, 133,0 }, + {2360,2360, 41, 0, 300, 113,0 }, + {2360,2360, 43, 0, 253, 106,0 }, + {2360,2360, 45, 0, 240, 100,0 }, + {2360,2360, 47, 0, 240, 100,0 }, + {2361,2362, 0, 4, 14720, 333,0 }, + {2363,2363, 0, 0, 7373, 1246,0 }, + {2364,2364, 0, 0, 4900, 233,0 }, + {2365,2365, 0, 0, 5106, 606,0 }, + {2366,2366, 0, 0, 1333, 153,0 }, + {2367,2367, 0, 0, 2093, 840,0 }, + {2368,2368, 0, 0, 3700, 226,0 }, + {2369,2369, 0, 0, 3546, 0,0 }, + {2370,2370, 0, 0, 4606, 420,0 }, + {2371,2371, 0, 0, 14366, 606,0 }, + {2372,2372, 0, 0, 40000, 426,0 }, + {2373,2373, 0, 0, 3700, 200,0 }, + {2374,2374, 0, 0, 880, 440,0 }, + {2375,2375, 0, 0, 4660, 660,0 }, + {2376,2376, 0, 0, 3600, 1153,0 }, + {2377,2377, 0, 0, 40000, 73,0 }, + {2378,2378, 0, 0, 40000, 53,0 }, + {2379,2379, 0, 0, 40000, 333,0 }, + {2380,2380, 0, 0, 40000, 73,0 }, + {2381,2381, 0, 0, 40000, 73,0 }, + {2382,2382, 0, 0, 40000, 66,0 }, + {2383,2383, 0, 0, 40000, 73,0 }, + {2384,2384, 0, 0, 40000, 73,0 }, + {2385,2385, 0, 0, 840, 226,0 }, + {2386,2386, 0, 0, 2093, 86,0 }, + {2387,2387, 0, 0, 906, 73,0 }, + { 402, 402, 0, 0, 273, 60,0 }, + {2388,2388, 0, 0, 40000, 820,0 }, + {2389,2389, 0, 0, 4740, 93,0 }, + {2390,2390, 0, 0, 706, 106,0 }, + {2391,2391, 0, 0, 40000, 0,0 }, + {2392,2392, 0, 0, 3840, 2306,0 }, + {2393,2393, 0, 0, 3400, 493,0 }, + {2394,2394, 0, 0, 40000, 53,0 }, + {2395,2395, 0, 0, 40000, 133,0 }, + {2396,2397, 0, 4, 3093, 1400,0 }, + {2398,2398, 0, 0, 1080, 580,0 }, + {2399,2400, 0, 4, 2220, 400,0 }, + {2401,2401, 0, 0, 40000, 193,0 }, + {2402,2402, 0, 0, 40000, 60,0 }, + {2403,2404, 0, 4, 40000, 146,0 }, + {2405,2406, 0, 4, 40000, 133,0 }, + {2407,2408, 0, 4, 40000, 66,0 }, + {2409,2409, 0, 0, 40000, 0,0 }, + {2410,2410, 0, 0, 40000, 73,0 }, + {2411,2411, 0, 0, 40000, 66,0 }, + {2412,2413, 0, 4, 40000, 153,0 }, + {2414,2414, 0, 0, 40000, 126,0 }, + {2415,2416, 0, 4, 40000, 466,0 }, + {2417,2418, 0, 4, 40000, 113,0 }, + {2419,2420, 0, 4, 1280, 73,0 }, + {2421,2422, 0, 4, 1113, 146,0 }, + {2423,2424, 0, 4, 3660, 113,0 }, + {2425,2426, 0, 4, 40000, 80,0 }, + {2427,2427, 33, 0, 300, 246,0 }, + {2428,2429, 38, 4, 53, 0,0 }, + {2430,2430, 38, 0, 106, 0,0 }, + {2431,2431, 38, 0, 340, 20,0 }, + {2432,2432, 40, 0, 73, 0,0 }, + {2433,2434, 41, 4, 300, 0,0 }, + {2435,2435, 0, 0, 133, 73,0 }, + {2435,2435, 41, 0, 133, 73,0 }, + {2360,2360, 48, 0, 240, 100,0 }, + {2436,2436, 17, 0, 4620, 1553,0 }, + {2360,2360, 50, 0, 240, 100,0 }, + {2435,2435, 45, 0, 126, 66,0 }, + {2437,2437,254, 2, 6, 0,0 }, + {2438,2438, 60, 0, 226, 93,0 }, + {2439,2439, 56, 0, 233, 93,0 }, + {2440,2440, 60, 0, 140, 66,0 }, + {2440,2440, 55, 0, 140, 60,0 }, + {2441,2441, 63, 0, 286, 126,0 }, + {2442,2442, 57, 0, 173, 93,0 }, + {2443,2443, 0, 0, 40000, 280,0 }, + {2444,2444, 0, 0, 40000, 0,0 }, + {2445,2445, 0, 0, 40000, 746,0 }, + {2446,2446, 0, 0, 40000, 353,0 }, + {2447,2447, 0, 0, 40000, 1173,0 }, + {2448,2448, 0, 0, 40000, 146,0 }, + {2449,2449, 0, 0, 40000, 1160,0 }, + {2450,2450, 0, 0, 40000, 353,0 }, + {2451,2451, 0, 0, 18313, 6046,0 }, + {2452,2452, 0, 0, 1206, 420,0 }, + { 752, 752, 55, 0, 173, 20,0 }, + {2453,2453, 0, 0, 2860, 806,0 }, + {2454,2454, 0, 0, 2506, 126,0 }, + {2455,2455, 0, 0, 520, 93,0 }, + {2456,2456, 0, 0, 1420, 160,0 }, + {2457,2457, 0, 0, 40000, 53,0 }, + {2458,2458, 0, 0, 9106, 100,0 }, + {2459,2459, 0, 0, 3706, 100,0 }, + {2460,2460, 0, 0, 17933, 100,0 }, + {2461,2461, 0, 0, 40000, 0,0 }, + {2462,2462, 0, 0, 40000, 66,0 }, + {2463,2463, 0, 0, 40000, 0,0 }, + { 884, 884, 0, 0, 306, 73,0 }, + { 884, 884, 28, 0, 306, 73,0 }, + {2464,2464, 29, 0, 226, 93,0 }, + { 886, 886, 31, 0, 113, 0,0 }, + { 360, 360, 32, 0, 133, 40,0 }, + { 361, 361, 33, 0, 286, 80,0 }, + {2453,2453, 34, 0, 2873, 813,0 }, + { 888, 888, 29, 0, 246, 46,0 }, + { 886, 886, 55, 0, 100, 0,0 }, + { 890, 890, 48, 0, 240, 60,0 }, + { 884, 884, 58, 0, 146, 26,0 }, + {2465,2465, 45, 0, 173, 93,0 }, + {2465,2465, 43, 0, 173, 93,0 }, + {2466,2466, 73, 0, 1633, 86,0 }, + {2467,2467, 72, 0, 866, 553,0 }, + {2468,2468, 76, 0, 1380, 0,0 }, + {2467,2467, 84, 0, 873, 560,0 }, + {2468,2468, 36, 0, 1933, 880,0 }, + {2469,2469, 65, 0, 300, 120,0 }, + {2470,2470, 83, 0, 193, 86,0 }, + {2471,2471, 50, 0, 966, 126,0 }, + {2468,2468, 77, 0, 1373, 620,0 }, + { 897, 897, 55, 0, 126, 40,0 }, + {2472,2472, 60, 0, 180, 140,0 }, + { 897, 897, 50, 0, 126, 40,0 }, + {2473,2473, 42, 0, 633, 240,0 }, + {2473,2473, 46, 0, 513, 200,0 }, + {2474,2474, 71, 0, 433, 180,0 }, + {2474,2474, 60, 0, 513, 206,0 }, + {2455,2455, 58, 0, 220, 46,0 }, + {2455,2455, 53, 0, 286, 60,0 }, + {2475,2475, 91, 0, 186, 100,0 }, + {2476,2476, 61, 0, 226, 26,0 }, + {2477,2477, 61, 0, 886, 73,0 }, + {2478,2478, 44, 0, 120, 73,0 }, + {2479,2479, 40, 0, 933, 73,0 }, + {2480,2480, 69, 0, 146, 33,0 }, + { 361, 361, 68, 0, 153, 26,0 }, + { 361, 361, 63, 0, 180, 26,0 }, + {2481,2481, 74, 0, 153, 73,0 }, + {2482,2482, 60, 0, 280, 100,0 }, + { 908, 908, 80, 0, 160, 26,0 }, + {2483,2483, 64, 0, 986, 353,0 }, + {2483,2483, 73, 0, 813, 306,0 }, + {2483,2483, 70, 0, 820, 306,0 }, + { 886, 886, 68, 0, 93, 0,0 }, + { 886, 886, 48, 0, 106, 0,0 }, + {2484,2484, 0, 0, 40000, 0,0 }, + {2485,2485, 0, 0, 3226, 753,0 }, + {2486,2486, 0, 0, 1773, 553,0 }, + {2487,2487, 0, 0, 7473, 2460,0 }, + {2488,2488, 0, 0, 40000, 0,0 }, + {2489,2489, 0, 0, 40000, 353,0 }, + {2490,2490, 0, 0, 40000, 206,0 }, + {2491,2491, 0, 0, 40000, 86,0 }, + {2492,2492, 0, 0, 4740, 86,0 }, + {2493,2493, 0, 0, 6193, 193,0 }, + {2494,2494, 0, 0, 6200, 240,0 }, + {2495,2495, 0, 0, 40000, 0,0 }, + {2496,2496, 0, 0, 1586, 73,0 }, + {2497,2497, 0, 0, 560, 73,0 }, + {2498,2498, 0, 0, 40000, 480,0 }, + {2499,2499, 0, 0, 40000, 80,0 }, + {2500,2500, 0, 0, 40000, 66,0 }, + {2501,2501, 0, 0, 40000, 380,0 }, + {2502,2502, 0, 0, 280, 100,0 }, + {2503,2503, 0, 0, 6193, 233,0 }, + {2504,2504, 0, 0, 40000, 380,0 }, + {2505,2505, 0, 0, 40000, 0,0 }, + {2506,2506, 0, 0, 40000, 380,0 }, + {2507,2507, 0, 0, 40000, 200,0 }, + {2508,2508, 0, 0, 40000, 320,0 }, + {2509,2509, 0, 0, 40000, 126,0 }, + {2510,2510, 0, 0, 40000, 293,0 }, + {2511,2511, 0, 0, 40000, 0,0 }, + {2512,2512, 0, 0, 40000, 40,0 }, + {2513,2513, 0, 0, 40000, 106,0 }, + {2514,2514, 0, 0, 3846, 73,0 }, + {2515,2515, 0, 0, 40000, 0,0 }, + {2516,2516, 0, 0, 40000, 73,0 }, + {2517,2517, 0, 0, 40000, 533,0 }, + {2518,2518, 0, 0, 40000, 1020,0 }, + {2519,2519, 0, 0, 40000, 73,0 }, + {2520,2520, 0, 0, 40000, 53,0 }, + {2521,2521, 0, 0, 6153, 1433,0 }, + {2522,2522, 0, 0, 18813, 773,0 }, + {2523,2523, 0, 0, 40000, 433,0 }, + {2524,2524, 0, 0, 40000, 0,0 }, + {2525,2525, 0, 0, 40000, 133,0 }, + {2526,2526, 0, 0, 4486, 73,0 }, + { 346, 346, 30, 0, 540, 33,0 }, + { 346, 346, 31, 0, 406, 20,0 }, + { 346, 346, 32, 0, 406, 20,0 }, + { 346, 346, 33, 0, 406, 73,0 }, + { 346, 346, 34, 0, 406, 20,0 }, + { 346, 346, 35, 0, 406, 20,0 }, + { 346, 346, 37, 0, 406, 73,0 }, + { 346, 346, 39, 0, 406, 73,0 }, + { 346, 346, 41, 0, 406, 20,0 }, + { 346, 346, 43, 0, 306, 20,0 }, + { 346, 346, 45, 0, 306, 20,0 }, + { 346, 346, 47, 0, 306, 20,0 }, + { 346, 346, 48, 0, 306, 20,0 }, + { 346, 346, 49, 0, 306, 20,0 }, + { 512, 512, 84, 0, 353, 466,0 }, + {2206,2206, 84, 0, 440, 180,0 }, + {2527,2527, 55, 0, 100, 0,0 }, + {2528,2528, 36, 0, 400, 160,0 }, + {2529,2529, 38, 0, 313, 226,0 }, + {2530,2530, 60, 0, 286, 133,0 }, + {2531,2531, 38, 0, 200, 100,0 }, + {2532,2532, 17, 0, 6186, 240,0 }, + {2532,2532, 18, 0, 6186, 240,0 }, + {2532,2532, 19, 0, 6193, 233,0 }, + {2532,2532, 20, 0, 6193, 193,0 }, + {2532,2532, 21, 0, 6193, 193,0 }, + {2532,2532, 22, 0, 6193, 193,0 }, + {2532,2532, 23, 0, 6193, 193,0 }, + {2532,2532, 24, 0, 6193, 193,0 }, + {2532,2532, 25, 0, 6193, 193,0 }, + {2532,2532, 26, 0, 6193, 193,0 }, + {2532,2532, 27, 0, 6193, 253,0 }, + {2532,2532, 28, 0, 6193, 246,0 }, + {2532,2532, 29, 0, 6193, 246,0 }, + {2533,2533, 84, 0, 433, 180,0 }, + {2534,2534, 48, 0, 280, 93,0 }, + {2535,2535, 65, 0, 1166, 360,0 }, + {2536,2536, 65, 0, 1853, 633,0 }, + {2537,2537, 55, 0, 453, 366,0 }, + {2537,2537, 41, 0, 540, 433,0 }, + { 346, 346, 63, 0, 240, 66,0 }, + { 346, 346, 55, 0, 240, 66,0 }, + {2538,2538, 55, 0, 2586, 200,0 }, + {2538,2538, 53, 0, 2586, 200,0 }, + {2534,2534, 50, 0, 280, 93,0 }, + { 506, 506, 84, 0, 693, 566,0 }, + { 506, 506, 74, 0, 693, 560,0 }, + { 504, 504, 84, 0, 1566, 546,0 }, + { 504, 504, 74, 0, 1586, 560,0 }, + {2539,2539, 84, 0, 440, 20,0 }, + {2540,2540, 74, 0, 126, 26,0 }, + {1911,1911, 48, 0, 500, 180,0 }, + {1911,1911, 36, 0, 606, 220,0 }, + {2541,2541, 74, 0, 686, 560,0 }, + {2542,2542, 0, 0, 7313, 13,0 }, + {2543,2543, 0, 0, 40000, 1306,0 }, + {2544,2544, 0, 0, 40000, 0,0 }, + {2545,2545, 0, 0, 4613, 13,0 }, + {2546,2547, 0, 4, 6933, 133,0 }, + {2548,2549, 0, 4, 40000, 86,0 }, + {2550,2550, 0, 0, 9233, 100,0 }, + {2551,2552, 0, 4, 4640, 73,0 }, + {2553,2553, 0, 0, 40000, 73,0 }, + {2554,2554, 0, 0, 40000, 0,0 }, + {2555,2556, 0, 4, 40000, 73,0 }, + {2557,2557, 0, 0, 40000, 60,0 }, + {2558,1467, 0, 4, 40000, 66,0 }, + {2559,2560, 0, 4, 40000, 40,0 }, + {2561,2561, 0, 0, 40000, 186,0 }, + {2562,2562, 0, 0, 4026, 66,0 }, + {2563,2564, 0, 4, 14586, 80,0 }, + {2565,2565, 0, 0, 40000, 0,0 }, + {2566,2567, 0, 4, 40000, 40,0 }, + {2568,2568, 0, 0, 4020, 73,0 }, + {2569,2569, 0, 0, 40000, 0,0 }, + {2570,2570, 0, 0, 40000, 0,0 }, + {2571,2572, 0, 4, 40000, 126,0 }, + {2573,2574, 0, 4, 40000, 100,0 }, + {2575,2575, 0, 0, 40000, 213,0 }, + { 229,2576, 0, 4, 40000, 166,0 }, + {2577,2577, 0, 0, 7366, 53,0 }, + { 239,2578, 0, 4, 40000, 133,0 }, + {2579,2579, 0, 0, 40000, 80,0 }, + {2580,2580, 0, 0, 40000, 140,0 }, + {2581,2582, 0, 4, 16980, 1173,0 }, + {2583,2584, 0, 4, 726, 100,0 }, + {2585,2586, 0, 4, 40000, 73,0 }, + {2587,2588, 0, 4, 40000, 73,0 }, + {2589,2589, 0, 0, 40000, 60,0 }, + {2590,2590, 0, 0, 40000, 80,0 }, + {2591,2592, 0, 4, 40000, 73,0 }, + {2593,2594, 0, 4, 40000, 60,0 }, + {2595,2595, 0, 0, 40000, 66,0 }, + {2596,2597, 0, 4, 40000, 66,0 }, + {2598,2599, 0, 4, 40000, 60,0 }, + {2600,2601, 0, 4, 40000, 173,0 }, + {2602,2602, 0, 0, 40000, 60,0 }, + {2603,2603, 0, 0, 40000, 73,0 }, + {2604,2604, 0, 0, 40000, 93,0 }, + {2605,2606, 0, 4, 40000, 73,0 }, + {2607,2607, 0, 0, 40000, 66,0 }, + {2608,2609, 0, 4, 40000, 66,0 }, + {2610,2610, 0, 0, 40000, 86,0 }, + {2611,2611, 0, 0, 40000, 60,0 }, + {2612,2612, 0, 0, 14286, 73,0 }, + {2613,2613, 0, 0, 40000, 0,0 }, + {2614,2615, 0, 4, 40000, 73,0 }, + {2616,2617, 0, 4, 40000, 66,0 }, + {2618,2619, 0, 4, 133, 0,0 }, + {2620,2621, 0, 4, 40000, 1280,0 }, + {2622,2623, 0, 4, 40000, 160,0 }, + {2624,2625, 0, 4, 40000, 0,0 }, + {2626,2627, 0, 4, 40000, 73,0 }, + {2628,2629, 0, 4, 40000, 0,0 }, + {1516,2630, 0, 4, 1193, 406,0 }, + {2631,2632, 0, 4, 40000, 553,0 }, + {2633,2633, 0, 0, 40000, 40,0 }, + {2634,2635, 0, 4, 40000, 773,0 }, + {2636,2636, 0, 0, 40000, 320,0 }, + {2637,2637, 0, 0, 1880, 73,0 }, + {2638,2639, 0, 4, 486, 0,0 }, + {2640,2641, 0, 4, 17020, 1193,0 }, + {2642,2642, 0, 0, 40000, 720,0 }, + {2643,2644, 0, 4, 1880, 40,0 }, + {2645,2645, 0, 0, 40000, 73,0 }, + {2646,2647, 0, 4, 40000, 46,0 }, + {2648,2648, 0, 0, 2466, 80,0 }, + {2649,2649, 0, 0, 40000, 193,0 }, + {2650,2651, 0, 4, 993, 73,0 }, + {2652,2652, 0, 0, 40000, 220,0 }, + {2653,2654, 0, 4, 40000, 46,0 }, + {2655,2656, 0, 4, 40000, 46,0 }, + {2657,2657, 0, 0, 40000, 66,0 }, + {2658,2658, 35, 0, 626, 20,0 }, + {2659,2659, 35, 0, 306, 26,0 }, + {2660,2660, 52, 0, 126, 26,0 }, + {2661,2661, 60, 0, 286, 20,0 }, + {2662,2662, 58, 0, 113, 0,0 }, + {2663,2663, 60, 0, 380, 20,0 }, + {2664,2664, 50, 0, 1640, 66,0 }, + {2665,2665, 43, 0, 153, 20,0 }, + {2664,2664, 55, 0, 1640, 20,0 }, + {1553,1553, 43, 0, 160, 80,0 }, + {2666,2666, 50, 0, 980, 20,0 }, + {2667,2667, 43, 0, 446, 73,0 }, + {2666,2666, 53, 0, 1000, 80,0 }, + {2666,2666, 57, 0, 700, 73,0 }, + {2668,2668, 72, 0, 773, 13,0 }, + {2666,2666, 60, 0, 686, 20,0 }, + { 373, 373, 76, 0, 826, 20,0 }, + {2669,2669, 84, 0, 713, 20,0 }, + {2670,2670, 42, 0, 1186, 20,0 }, + {2671,2671, 65, 0, 293, 33,0 }, + {2672,2672, 84, 0, 386, 33,0 }, + {2673,2673, 84, 0, 1366, 20,0 }, + {2674,2674, 24, 0, 960, 73,0 }, + { 383, 383, 77, 0, 800, 20,0 }, + {2675,2675, 58, 0, 426, 26,0 }, + {2676,2676, 53, 0, 426, 20,0 }, + {2677,2677, 64, 0, 200, 66,0 }, + {2678,2678, 71, 0, 113, 13,0 }, + {2679,2679, 44, 0, 766, 66,0 }, + {2680,2680, 40, 0, 460, 60,0 }, + {2681,2681, 69, 0, 126, 26,0 }, + {2682,2682, 60, 0, 573, 66,0 }, + {2683,2683, 80, 0, 226, 20,0 }, + {2684,2684, 64, 0, 2693, 20,0 }, + {2685,2685, 72, 0, 120, 66,0 }, + {2686,2686, 70, 0, 820, 20,0 }, + {2687,2687, 48, 0, 173, 20,0 }, + {2688,2688, 53, 0, 980, 33,0 }, + {2689,2690, 0, 4, 40000, 286,0 }, + {2691,2692, 0, 4, 2340, 100,0 }, + {2693,2694, 0, 4, 380, 80,0 }, + {2695,2696, 0, 4, 14793, 73,0 }, + {2697,2698, 0, 4, 40000, 40,0 }, + { 192,2699, 0, 4, 40000, 73,0 }, + {2700,2701, 0, 4, 973, 126,0 }, + {2702,2703, 0, 4, 4666, 106,0 }, + {2704,2705, 0, 4, 40000, 73,0 }, + {2706,2707, 0, 4, 40000, 73,0 }, + {2708,2709, 0, 4, 40000, 73,0 }, + {2710,2711, 0, 4, 2053, 0,0 }, + {2712,1473, 0, 4, 320, 26,0 }, + {2713,2714, 0, 4, 573, 93,0 }, + {2715,2716, 0, 4, 6513, 0,0 }, + {1478,2717, 0, 4, 40000, 146,0 }, + {2718,2719, 0, 4, 40000, 66,0 }, + { 286,2720, 0, 4, 40000, 73,0 }, + {2721,2722, 0, 4, 40000, 86,0 }, + {2723,2724, 0, 4, 40000, 60,0 }, + {2725,2726, 0, 4, 393, 73,0 }, + {2727,2724, 0, 4, 40000, 60,0 }, + {1514,2728, 0, 4, 40000, 180,0 }, + {2729,2730, 0, 4, 40000, 0,0 }, + {2731,2732, 0, 4, 486, 0,0 }, + {2733,2734, 0, 4, 733, 0,0 }, + {2735,2736, 0, 4, 286, 40,0 }, + {2737,2738, 0, 4, 40000, 73,0 }, + {2739,2740, 0, 4, 1326, 746,0 }, + {2741,2742, 0, 4, 1340, 700,0 }, + {2743,2744, 0, 4, 40000, 0,0 }, + {2745,2746, 0, 4, 2046, 0,0 }, + {2747,2747, 35, 0, 386, 166,0 }, + {2748,2748, 60, 0, 493, 193,0 }, + {2749,2749, 43, 0, 126, 66,0 }, + {2750,2750, 0, 0, 3740, 1260,0 }, + {2751,2752, 0, 4, 14846, 353,0 }, + {2753,2754, 0, 4, 10266, 0,0 }, + {2755,2756, 0, 4, 18286, 146,0 }, + {2757,2758, 0, 4, 14520, 333,0 }, + {2759,2760, 0, 4, 14686, 633,0 }, + {2761,2762, 0, 4, 14826, 300,0 }, + {2763,2764, 0, 4, 10493, 0,0 }, + {2765,2766, 0, 4, 40000, 60,0 }, + {2767,2768, 0, 4, 40000, 80,0 }, + {2769,2770, 0, 4, 40000, 80,0 }, + {2771,2772, 0, 4, 40000, 73,0 }, + {2773,2774, 0, 4, 40000, 73,0 }, + {2775,2776, 0, 4, 40000, 80,0 }, + {2777,2778, 0, 4, 40000, 73,0 }, + {2779,2780, 0, 4, 40000, 73,0 }, + {2781,2782, 0, 4, 40000, 66,0 }, + {2783,2784, 0, 4, 7260, 186,0 }, + {2785,2786, 0, 4, 10386, 0,0 }, + {2787,2788, 0, 4, 40000, 246,0 }, + {2789,2790, 0, 4, 9173, 746,0 }, + {2791,2792, 0, 4, 7440, 666,0 }, + {2793,2794, 0, 4, 40000, 0,0 }, + {2795,2796, 0, 4, 40000, 413,0 }, + {2795,2797, 0, 4, 40000, 1506,0 }, + {2798,2799, 0, 4, 40000, 60,0 }, + {2800,2801, 0, 4, 40000, 233,0 }, + {2802,2803, 0, 4, 40000, 80,0 }, + {2804,2805, 0, 4, 40000, 80,0 }, + {2806,2807, 0, 4, 4520, 80,0 }, + {2808,2809, 0, 4, 40000, 73,0 }, + {2810,2811, 0, 4, 1186, 100,0 }, + {2812,2813, 0, 4, 953, 153,0 }, + {2814,2815, 0, 4, 14786, 126,0 }, + {2816,2817, 0, 4, 14800, 193,0 }, + {2818,2819, 0, 4, 14573, 626,0 }, + {2820,2821, 0, 4, 2200, 73,0 }, + {2822,2823, 0, 4, 373, 86,0 }, + {2824,2825, 0, 4, 12780, 200,0 }, + {2826,2827, 0, 4, 40000, 73,0 }, + {2828,2829, 0, 4, 9193, 146,0 }, + {2830,2831, 0, 4, 2540, 326,0 }, + {2832,2833, 0, 4, 6933, 200,0 }, + {2834,2835, 0, 4, 40000, 413,0 }, + {2836,2837, 0, 4, 4826, 1313,0 }, + {2838,2839, 0, 4, 14740, 340,0 }, + {2840,2841, 0, 4, 1886, 653,0 }, + {2842,2843, 0, 4, 5280, 260,0 }, + {2844,2845, 0, 4, 40000, 240,0 }, + {2846,2847, 0, 4, 40000, 240,0 }, + {2848,2849, 0, 4, 40000, 240,0 }, + {2850,2851, 0, 4, 40000, 406,0 }, + {2852,2853, 0, 4, 40000, 406,0 }, + {2854,2855, 0, 4, 40000, 146,0 }, + {2856,2856, 0, 0, 2400, 1126,0 }, + {2857,2857, 0, 0, 2400, 1126,0 }, + {2858,2859, 0, 4, 4613, 73,0 }, + {2860,2861, 0, 4, 40000, 426,0 }, + {2862,2863, 0, 4, 4580, 100,0 }, + {2864,2865, 0, 4, 40000, 80,0 }, + {2866,2867, 0, 4, 5300, 53,0 }, + {2868,2869, 0, 4, 5313, 113,0 }, + {2870,2871, 0, 4, 7080, 186,0 }, + {2872,2873, 0, 4, 4720, 106,0 }, + {2874,2875, 0, 4, 40000, 73,0 }, + {2876,2877, 0, 4, 1640, 0,0 }, + {2878,2879, 0, 4, 7306, 186,0 }, + {2880,2881, 0, 4, 7373, 1246,0 }, + {2882,2883, 0, 4, 4620, 93,0 }, + {2884,2885, 0, 4, 3460, 926,0 }, + {2886,2887, 0, 4, 40000, 73,0 }, + {2888,2888, 0, 0, 18926, 426,0 }, + {2889,2889, 0, 0, 18520, 73,0 }, + {2890,2890, 0, 0, 18473, 73,0 }, + {2891,2892, 0, 4, 40000, 93,0 }, + {2893,2893, 0, 0, 8006, 133,0 }, + {2894,2894, 0, 0, 18533, 66,0 }, + {2895,2895, 0, 0, 14786, 4966,0 }, + {2896,2897, 0, 4, 40000, 80,0 }, + {2898,2899, 0, 4, 40000, 73,0 }, + {2353,2900, 0, 4, 18520, 86,0 }, + {2901,2901, 0, 0, 40000, 0,0 }, + {2902,2903, 0, 4, 40000, 100,0 }, + {2904,2905, 0, 4, 40000, 93,0 }, + {2906,2907, 0, 4, 40000, 73,0 }, + {2908,2909, 0, 4, 10720, 153,0 }, + {2910,2911, 0, 4, 40000, 73,0 }, + {2912,2912, 0, 0, 40000, 40,0 }, + {2913,2914, 0, 4, 8720, 446,0 }, + {2915,2916, 0, 4, 14706, 653,0 }, + {2917,2918, 0, 4, 9213, 426,0 }, + {2919,2920, 0, 4, 9286, 240,0 }, + {2921,2922, 0, 4, 8706, 413,0 }, + {2923,2924, 0, 4, 2233, 346,0 }, + {2925,2926, 0, 4, 2373, 426,0 }, + {2927,2928, 0, 4, 2353, 233,0 }, + {2929,2929, 0, 0, 40000, 140,0 }, + {2930,2931, 0, 4, 40000, 100,0 }, + {2932,2933, 0, 4, 40000, 73,0 }, + {2934,2935, 0, 4, 40000, 80,0 }, + {2936,2937, 0, 4, 40000, 80,0 }, + {2938,2939, 0, 4, 40000, 246,0 }, + {2940,2940, 0, 0, 553, 446,0 }, + {2941,2941, 0, 0, 40000, 193,0 }, + {2942,2943, 0, 4, 1206, 406,0 }, + {2944,2944, 0, 0, 7026, 1553,0 }, + {2945,2945, 0, 0, 3426, 360,0 }, + {2946,2947, 0, 4, 7313, 646,0 }, + {2948,2948, 0, 0, 40000, 386,0 }, + {2949,2949, 0, 0, 1953, 726,0 }, + {2950,2951, 0, 4, 14606, 106,0 }, + {2952,2953, 0, 4, 40000, 1566,0 }, + {2954,2954, 60, 2, 6, 0,0 }, + {2955,2956, 0, 4, 40000, 240,0 }, + {2957,2958, 0, 4, 40000, 80,0 }, + {2959,2960, 0, 4, 40000, 113,0 }, + {2961,2962, 0, 4, 40000, 240,0 }, + {2963,2963, 0, 0, 8506, 680,0 }, + {2964,2964, 0, 0, 40000, 1593,0 }, + {2436,2436, 49, 0, 1873, 633,0 }, + {2357,2357, 61, 0, 113, 20,0 }, + {2357,2357, 56, 0, 113, 26,0 }, + {2357,2357, 58, 0, 113, 26,0 }, + {2357,2357, 49, 0, 126, 26,0 }, + {2357,2357, 44, 0, 126, 26,0 }, + {2965,2965, 0, 0, 40000, 380,0 }, + {2966,2966, 0, 0, 4440, 66,0 }, + {2967,2967, 0, 0, 8133, 1433,0 }, + {2968,2968, 0, 0, 40000, 126,0 }, + {2969,2969, 0, 0, 40000, 0,0 }, + {2970,2970, 84, 0, 160, 26,0 }, + {2971,2971, 72, 0, 440, 180,0 }, + {2972,2972, 0, 0, 8313, 580,0 }, + {2973,2973, 0, 0, 40000, 160,0 }, + {2974,2974, 0, 0, 40000, 3000,0 }, + {2975,2975, 0, 0, 8300, 493,0 }, + {2976,2976, 0, 0, 973, 673,0 }, + {2977,2977, 0, 0, 40000, 73,0 }, + {2978,2978, 0, 0, 40000, 133,0 }, + {2979,2979, 0, 0, 40000, 140,0 }, + {2980,2980, 0, 0, 40000, 346,0 }, + {2981,2981, 0, 0, 40000, 1006,0 }, + {2982,2982, 0, 0, 40000, 966,0 }, + {2983,2983, 0, 0, 40000, 0,0 }, + {2984,2984, 0, 0, 40000, 0,0 }, + {2985,2985, 0, 0, 40000, 66,0 }, + {2986,2986, 0, 0, 40000, 66,0 }, + {2987,2987, 0, 0, 40000, 46,0 }, + {2988,2988, 0, 0, 40000, 533,0 }, + {2989,2989, 0, 0, 2400, 780,0 }, + {2990,2990, 0, 0, 820, 66,0 }, + {2991,2991, 0, 0, 40000, 240,0 }, + {2992,2992, 0, 0, 40000, 220,0 }, + {2993,2993, 0, 0, 40000, 0,0 }, + {2994,2994, 0, 0, 15100, 73,0 }, + {2995,2995, 0, 0, 40000, 200,0 }, + {2996,2996, 0, 0, 2426, 93,0 }, + {2997,2997, 0, 0, 4640, 1553,0 }, + {2998,2998, 0, 0, 40000, 73,0 }, + {2999,2999, 0, 0, 40000, 73,0 }, + {3000,3000, 0, 0, 1133, 633,0 }, + {3001,3001, 0, 0, 40000, 0,0 }, + {3002,3002, 0, 0, 40000, 1006,0 }, + {3003,3003, 0, 0, 4653, 653,0 }, + {3004,3004, 0, 0, 40000, 1000,0 }, + {3005,3005, 0, 0, 40000, 53,0 }, + {3006,3006, 0, 0, 40000, 60,0 }, + {3007,3007, 0, 0, 40000, 0,0 }, + { 350, 350, 0, 0, 513, 200,0 }, + {3008,3008, 0, 0, 213, 106,0 }, + {3009,3009, 0, 0, 280, 126,0 }, + {3010,3010, 0, 0, 1193, 426,0 }, + {3011,3011, 0, 0, 14653, 4906,0 }, + {3012,3012, 0, 0, 1040, 326,0 }, + {3013,3013, 0, 0, 5740, 2326,0 }, + {3014,3014, 0, 0, 40000, 73,0 }, + {3015,3015, 0, 0, 40000, 240,0 }, + { 350, 350, 36, 0, 380, 153,0 }, + { 369, 369, 37, 0, 213, 66,0 }, + {3008,3008, 38, 0, 213, 106,0 }, + { 369, 369, 24, 0, 193, 13,0 }, + {3008,3008, 32, 0, 206, 106,0 }, + { 369, 369, 48, 0, 186, 20,0 }, + {3009,3009, 42, 0, 220, 106,0 }, + { 369, 369, 50, 0, 186, 73,0 }, + { 369, 369, 52, 0, 186, 73,0 }, + { 369, 369, 54, 0, 186, 33,0 }, + { 369, 369, 55, 0, 186, 33,0 }, + { 369, 369, 57, 0, 180, 33,0 }, + {3010,3010, 51, 0, 966, 353,0 }, + { 144, 144, 61, 0, 213, 126,0 }, + {3016,3016, 0, 0, 8340, 520,0 }, + {3016,3016, 63, 0, 6106, 373,0 }, + {3016,3016, 64, 0, 6073, 380,0 }, + {3017,3017, 40, 0, 206, 100,0 }, + {3017,3017, 70, 0, 160, 93,0 }, + {3018,3018, 0, 0, 40000, 73,0 }, + {3019,3019, 0, 0, 40000, 73,0 }, + {3020,3020, 0, 0, 40000, 73,0 }, + {3021,3021, 0, 0, 40000, 73,0 }, + {3022,3022, 38, 0, 246, 33,0 }, + {2441,2441, 57, 0, 286, 126,0 }, + {3023,3023, 63, 0, 146, 126,0 }, + {3024,3024, 74, 0, 280, 73,0 }, + {3025,3025, 74, 0, 453, 100,0 }, + {3026,3026, 60, 0, 666, 33,0 }, + {1439,1440, 0, 0, 13566, 273,0 }, + {1593,1594, 35, 0, 2200, 673,0 }, + {1564,1565, 35, 0, 740, 280,0 }, + {1443,1444, 0, 0, 11886, 333,0 }, + {1481,1482, 0, 0, 40000, 133,0 }, + { 185, 186, 0, 0, 5980, 1540,0 }, + { 235, 237, 0, 0, 3366, 1093,0 }, + { 239, 240, 0, 0, 40000, 133,0 }, + {1477,1476, 0, 0, 40000, 160,0 }, + { 268, 269, 0, 0, 40000, 80,0 }, + { 176, 177, 0, 0, 40000, 0,0 }, + {1490,1491, 0, 0, 40000, 60,0 }, + { 231, 232, 0, 0, 40000, 146,0 }, + { 233, 234, 0, 0, 40000, 433,0 }, + { 254, 255, 0, 0, 40000, 93,0 }, + { 192, 193, 0, 0, 40000, 66,0 }, + { 252, 253, 0, 0, 40000, 73,0 }, + { 248,3027, 0, 0, 40000, 80,0 }, + { 39,1476, 0, 0, 40000, 160,0 }, + { 241, 242, 0, 0, 40000, 146,0 }, + {1508,1509, 0, 0, 40000, 0,0 }, + { 246, 247, 0, 0, 3966, 800,0 }, + { 181,1451, 0, 0, 2153, 640,0 }, + { 209, 210, 0, 0, 4453, 100,0 }, + { 270, 271, 0, 0, 40000, 80,0 }, + { 115,1533, 0, 0, 4260, 1720,0 }, + {1454,1455, 0, 0, 40000, 0,0 }, + { 107, 319, 0, 0, 1266, 413,0 }, + { 46, 238, 0, 0, 6873, 1246,0 }, + { 216, 217, 0, 0, 4046, 100,0 }, + { 272, 273, 0, 0, 40000, 126,0 }, + {1445,3028, 0, 0, 9966, 386,0 }, + { 172, 173, 0, 0, 7340, 100,0 }, + { 174, 175, 0, 0, 6913, 100,0 }, + {1447,3029, 0, 0, 10306, 80,0 }, + {1452,3030, 0, 0, 9240, 240,0 }, + { 183, 184, 0, 0, 586, 253,0 }, + {1456,1457, 0, 0, 1386, 180,0 }, + {1458,1459, 0, 0, 40000, 60,0 }, + { 190,1460, 0, 0, 40000, 46,0 }, + {1462,1463, 0, 0, 40000, 340,0 }, + {1464,1465, 0, 0, 40000, 360,0 }, + { 195, 196, 0, 0, 40000, 66,0 }, + { 197, 198, 0, 0, 40000, 86,0 }, + { 199, 200, 0, 0, 40000, 60,0 }, + { 201, 202, 0, 0, 3713, 100,0 }, + { 203, 204, 0, 0, 14633, 126,0 }, + { 205, 206, 0, 0, 9440, 153,0 }, + { 214, 215, 0, 0, 17020, 100,0 }, + { 218, 219, 0, 0, 14000, 180,0 }, + { 220, 221, 0, 0, 2846, 100,0 }, + {1472,1473, 0, 0, 8066, 66,0 }, + {1474,1475, 0, 0, 8040, 93,0 }, + { 225, 226, 0, 0, 8066, 106,0 }, + { 229, 230, 0, 0, 40000, 160,0 }, + {1478,1479, 0, 0, 40000, 413,0 }, + { 50,1480, 0, 0, 40000, 393,0 }, + {1485,1486, 0, 0, 40000, 226,0 }, + { 258, 259, 0, 0, 40000, 73,0 }, + { 262, 263, 0, 0, 40000, 160,0 }, + { 264, 265, 0, 0, 40000, 160,0 }, + {1494,1495, 0, 0, 40000, 80,0 }, + {1496,1497, 0, 0, 40000, 73,0 }, + { 274, 275, 0, 0, 40000, 100,0 }, + {1499,1500, 0, 0, 40000, 73,0 }, + { 277, 278, 0, 0, 40000, 173,0 }, + { 279, 280, 0, 0, 40000, 160,0 }, + { 281, 282, 0, 0, 40000, 173,0 }, + {1501,1502, 0, 0, 40000, 146,0 }, + { 284, 285, 0, 0, 40000, 66,0 }, + { 286, 287, 0, 0, 40000, 86,0 }, + {1503,1504, 0, 0, 40000, 86,0 }, + {1505,1506, 0, 0, 40000, 73,0 }, + { 289, 290, 0, 0, 40000, 66,0 }, + { 291, 292, 0, 0, 40000, 160,0 }, + { 293, 294, 0, 0, 40000, 200,0 }, + { 86,1507, 0, 0, 40000, 80,0 }, + { 88, 297, 0, 0, 40000, 1346,0 }, + { 298, 299, 0, 0, 40000, 320,0 }, + { 300, 301, 0, 0, 40000, 1273,0 }, + {1514,1515, 0, 0, 40000, 100,0 }, + {1518,1519, 0, 0, 4733, 0,0 }, + {1520,1521, 0, 0, 40000, 440,0 }, + {1524,1525, 0, 0, 40000, 1180,0 }, + {1526,1527, 0, 0, 40000, 746,0 }, + {1528,1529, 0, 0, 40000, 920,0 }, + { 311, 312, 0, 0, 15306, 213,0 }, + { 313, 314, 0, 0, 7280, 340,0 }, + { 315, 316, 0, 0, 3693, 346,0 }, + { 317, 318, 0, 0, 13720, 4033,0 }, + { 108, 320, 0, 0, 40000, 66,0 }, + { 109, 321, 0, 0, 40000, 180,0 }, + { 322, 323, 0, 0, 40000, 73,0 }, + { 111,1530, 0, 0, 4053, 426,0 }, + { 324, 325, 0, 0, 626, 260,0 }, + { 326, 327, 0, 0, 1166, 400,0 }, + {1531,1532, 0, 0, 186, 340,0 }, + {1534,1535, 0, 0, 3240, 440,0 }, + { 330, 331, 0, 0, 1920, 360,0 }, + {1536,1537, 0, 0, 3020, 0,0 }, + {1538,1539, 0, 0, 1660, 846,0 }, + {1541, 339, 0, 0, 9213, 813,0 }, + {1542,1543, 0, 0, 993, 100,0 }, + {1544,3031, 0, 0, 860, 180,0 }, + {1546,3032, 0, 0, 40000, 80,0 }, + { 338, 339, 0, 0, 40000, 200,0 }, + { 340, 341, 0, 0, 40000, 0,0 }, + {1441,1442, 0, 0, 7393, 186,0 }, + { 207, 208, 0, 0, 14373, 126,0 }, + {1466,1467, 0, 0, 40000, 66,0 }, + {1468,1469, 0, 0, 40000, 46,0 }, + { 179, 180, 0, 0, 4080, 346,0 }, + {1449,1450, 0, 0, 8313, 3373,0 }, + { 35,1470, 0, 0, 40000, 0,0 }, + { 36,1471, 0, 0, 8093, 40,0 }, + { 235, 236, 0, 0, 2393, 333,0 }, + {1483,1484, 0, 0, 40000, 0,0 }, + { 55,1487, 0, 0, 40000, 80,0 }, + {1488,1489, 0, 0, 40000, 80,0 }, + {1492,1493, 0, 0, 40000, 66,0 }, + { 256, 257, 0, 0, 40000, 53,0 }, + { 260, 261, 0, 0, 40000, 86,0 }, + {1512,1513, 0, 0, 40000, 40,0 }, + {1510,1511, 0, 0, 40000, 80,0 }, + {1496,1498, 0, 0, 40000, 73,0 }, + { 295, 296, 0, 0, 40000, 340,0 }, + {1540, 339, 0, 0, 2466, 633,0 }, + { 398, 399, 35, 0, 1860, 226,0 }, + {1516,1517, 0, 0, 40000, 660,0 }, + {1550,3033, 35, 0, 213, 26,0 }, + {1556,1557, 35, 0, 1200, 426,0 }, + {1558,1559, 35, 0, 1173, 406,0 }, + {1570,1571, 35, 0, 1160, 140,0 }, + {1608,1609, 35, 0, 2100, 320,0 }, + {1595,1596, 35, 0, 220, 273,0 }, + { 159,1597, 35, 0, 220, 266,0 }, + {1610,1611, 35, 0, 220, 273,0 }, + { 397,1588, 35, 0, 253, 86,0 }, + {1606,1607, 35, 0, 133, 66,0 }, + { 145,1576, 35, 0, 180, 0,0 }, + {1612,1613, 35, 0, 526, 400,0 }, + {1577,1578, 35, 0, 506, 453,0 }, + {1614,1615, 35, 0, 773, 933,0 }, + { 305, 306, 0, 0, 40000, 1160,0 }, + {1522,1523, 0, 0, 40000, 0,0 }, + {1550,1551, 35, 0, 526, 146,0 }, + { 364, 365, 35, 0, 186, 20,0 }, + { 129,1549, 35, 0, 326, 133,0 }, + { 132,1552, 35, 0, 226, 113,0 }, + {1553,1554, 35, 0, 206, 73,0 }, + { 129,1548, 35, 0, 326, 133,0 }, + { 134,1555, 35, 0, 2580, 893,0 }, + {1560,1561, 35, 0, 600, 366,0 }, + {1562,1563, 35, 0, 40000, 0,0 }, + {1572,1573, 35, 0, 340, 133,0 }, + {1574,1575, 35, 0, 406, 226,0 }, + {1581,1582, 35, 0, 640, 213,0 }, + { 149,1583, 35, 0, 326, 20,0 }, + {1584,1585, 35, 0, 633, 240,0 }, + {1591,1592, 35, 0, 1226, 413,0 }, + {1568,1569, 35, 0, 1313, 460,0 }, + {1579,1580, 35, 0, 326, 0,0 }, + {1586,1587, 35, 0, 606, 220,0 }, + {1589,1590, 35, 0, 120, 86,0 }, + {1600,1601, 35, 0, 1326, 420,0 }, + {1602,1603, 35, 0, 706, 266,0 }, + {1604,1605, 35, 0, 4540, 1326,0 }, + { 391, 392, 35, 0, 360, 153,0 }, + { 391, 393, 35, 0, 453, 153,0 }, + {1598,1599, 35, 0, 1246, 346,0 }, + { 367, 368, 35, 0, 600, 153,0 }, + { 380, 381, 35, 0, 40000, 0,0 }, + { 374, 375, 35, 0, 40000, 0,0 }, + {1566,1567, 35, 0, 40000, 0,0 }, + {2306,2307, 35, 0, 7660, 1560,0 }, + {3034, 339, 35, 0, 5860, 426,0 }, + {2301,2302, 35, 0, 2146, 753,0 }, + {2305,1548, 35, 0, 326, 133,0 }, + {1595,1595, 35, 0, 220, 273,0 }, + {2303,2304, 35, 0, 186, 20,0 }, + {1560,2308, 35, 0, 600, 373,0 }, + {2309,2310, 35, 0, 40000, 0,0 }, + {1568,1568, 35, 0, 1280, 453,0 }, + {2311,2312, 35, 0, 360, 106,0 }, + {2313,2314, 35, 0, 620, 0,0 }, + {2315,2315, 35, 0, 106, 0,0 }, + {2316,2316, 35, 0, 506, 453,0 }, + {1612,1612, 35, 0, 526, 400,0 }, + {2317,2317, 35, 0, 640, 253,0 }, + {2318,2318, 35, 0, 326, 20,0 }, + {2319,2319, 35, 0, 453, 446,0 }, + {2320,2320, 35, 0, 466, 453,0 }, + {2321,2321, 35, 0, 120, 26,0 }, + {2322,2322, 35, 0, 1220, 406,0 }, + {2323,2323, 35, 0, 2360, 786,0 }, + {2324, 392, 35, 0, 353, 146,0 }, + {2324, 393, 35, 0, 453, 146,0 }, + {2325,2326, 35, 0, 533, 140,0 }, + {2327,2328, 35, 0, 1273, 393,0 }, + {2329,2330, 35, 0, 40000, 0,0 }, + {2331,2332, 35, 0, 40000, 0,0 }, + {3035,3036, 35, 0, 4133, 433,0 }, + {3037,3038, 35, 0, 1740, 286,0 }, + {1564,1564, 35, 0, 713, 273,0 }, + {3039,3039, 0, 0, 40000, 0,0 }, + {3040,3040, 0, 0, 6100, 146,0 }, + {3041,3041, 0, 0, 2386, 26,0 }, + {3042,3042, 0, 0, 4320, 80,0 }, + {3043,3043, 0, 0, 3433, 313,0 }, + {3044,3044, 0, 0, 6620, 2446,0 }, + {3045,3045, 0, 0, 3726, 1253,0 }, + {3046,3046, 0, 0, 40000, 133,0 }, + {3047,3047, 0, 0, 4566, 1253,0 }, + {3048,3048, 0, 0, 40000, 813,0 }, + {3049,3049, 0, 0, 18513, 1560,0 }, + {3050,3050, 0, 0, 2186, 426,0 }, + {3051,3051, 0, 0, 1186, 420,0 }, + {3052,3052, 0, 0, 766, 420,0 }, + {3053,3053, 0, 0, 14513, 4713,0 }, + {3054,3054, 0, 0, 15493, 1580,0 }, + {3055,3055, 0, 0, 40000, 66,0 }, + {3056,3056, 0, 0, 40000, 60,0 }, + {3057,3057, 0, 0, 4740, 100,0 }, + {3058,3058, 0, 0, 40000, 66,0 }, + {3059,3059, 0, 0, 40000, 73,0 }, + {3060,3060, 0, 0, 40000, 73,0 }, + {3061,3061, 0, 0, 40000, 0,0 }, + {3062,3062, 0, 0, 8373, 633,0 }, + {3063,3063, 0, 0, 7560, 133,0 }, + {3064,3064, 0, 0, 40000, 0,0 }, + {3065,3065, 0, 0, 40000, 86,0 }, + {3066,3066, 0, 0, 340, 140,0 }, + {3067,3067, 0, 0, 40000, 0,0 }, + {3068,3068, 0, 0, 40000, 166,0 }, + {3069,3069, 0, 0, 4280, 1466,0 }, + {3070,3070, 0, 0, 2193, 73,0 }, + {3071,3071, 0, 0, 4846, 100,0 }, + {3072,3072, 0, 0, 12740, 93,0 }, + {3073,3073, 0, 0, 6953, 200,0 }, + {3074,3074, 0, 0, 13780, 73,0 }, + {3075,3075, 0, 0, 40000, 73,0 }, + {3076,3076, 0, 0, 5860, 600,0 }, + {3077,3077, 0, 0, 2206, 73,0 }, + {3078,3078, 0, 0, 40000, 140,0 }, + {3079,3079, 0, 0, 40000, 53,0 }, + {3080,3080, 0, 0, 40000, 120,0 }, + {3081,3081, 0, 0, 40000, 140,0 }, + {3082,3082, 0, 0, 40000, 126,0 }, + {3083,3083, 0, 0, 360, 140,0 }, + {3084,3084, 0, 0, 8880, 1373,0 }, + {3085,3085, 0, 0, 593, 73,0 }, + {3086,3086, 0, 0, 40000, 193,0 }, + {3087,3087, 0, 0, 40000, 200,0 }, + {3088,3088, 0, 0, 40000, 160,0 }, + {3089,3089, 0, 0, 40000, 200,0 }, + {3090,3090, 0, 0, 40000, 53,0 }, + {3091,3091, 0, 0, 40000, 73,0 }, + {3092,3092, 0, 0, 40000, 73,0 }, + {3093,3093, 0, 0, 760, 213,0 }, + {3094,3094, 0, 0, 40000, 133,0 }, + {3095,3095, 0, 0, 40000, 220,0 }, + {3096,3096, 0, 0, 40000, 100,0 }, + {3097,3097, 0, 0, 40000, 73,0 }, + {3098,3098, 0, 0, 40000, 140,0 }, + {3099,3099, 0, 0, 40000, 140,0 }, + {3100,3100, 0, 0, 40000, 140,0 }, + {3101,3101, 0, 0, 40000, 73,0 }, + {3102,3102, 0, 0, 40000, 73,0 }, + {3103,3103, 0, 0, 40000, 73,0 }, + {3104,3104, 0, 0, 40000, 73,0 }, + {3105,3105, 0, 0, 40000, 66,0 }, + {3106,3106, 0, 0, 40000, 66,0 }, + {3107,3107, 0, 0, 40000, 73,0 }, + {3108,3108, 0, 0, 40000, 73,0 }, + {3109,3109, 0, 0, 40000, 73,0 }, + {3110,3110, 0, 0, 40000, 73,0 }, + {3111,3111, 0, 0, 40000, 86,0 }, + {3112,3112, 0, 0, 5393, 100,0 }, + {3113,3113, 0, 0, 40000, 60,0 }, + {3114,3114, 0, 0, 18500, 73,0 }, + {3115,3115, 0, 0, 40000, 93,0 }, + {3116,3116, 0, 0, 40000, 86,0 }, + {3117,3117, 0, 0, 40000, 173,0 }, + {3118,3118, 0, 0, 40000, 1353,0 }, + {3119,3119, 0, 0, 17506, 73,0 }, + {3120,3120, 0, 0, 40000, 100,0 }, + {3121,3121, 0, 0, 40000, 73,0 }, + {3122,3122, 0, 0, 5620, 193,0 }, + {3123,3123, 0, 0, 3700, 80,0 }, + {3124,3124, 0, 0, 40000, 66,0 }, + {3125,3125, 0, 0, 2740, 80,0 }, + {3126,3126, 0, 0, 8333, 173,0 }, + {3127,3127, 0, 0, 2226, 466,0 }, + {3128,3128, 0, 0, 340, 146,0 }, + {3129,3129, 0, 0, 19980, 6280,0 }, + {3130,3130, 0, 0, 353, 73,0 }, + {3131,3131, 35, 0, 566, 233,0 }, + {3132,3132, 35, 0, 226, 46,0 }, + {3133,3133, 35, 0, 40000, 100,0 }, + {3134,3134, 35, 0, 40000, 100,0 }, + {3135,3135, 35, 0, 360, 146,0 }, + {3061,3061, 35, 0, 40000, 0,0 }, + {3136,3136, 35, 0, 366, 20,0 }, + { 739, 739, 35, 0, 246, 20,0 }, + {3137,3137, 35, 0, 333, 33,0 }, + {3138,3138, 35, 0, 420, 166,0 }, + {3139,3139, 35, 0, 626, 240,0 }, + {3140,3140, 35, 0, 233, 100,0 }, + {3141,3141, 35, 0, 1166, 440,0 }, + {3142,3142, 35, 0, 166, 66,0 }, + {3143,3143, 35, 0, 1166, 440,0 }, + {3144,3144, 35, 0, 813, 100,0 }, + {3145,3145, 35, 0, 1040, 440,0 }, + {3146,3146, 35, 0, 40000, 0,0 }, + {3147,3147, 35, 0, 40000, 0,0 }, + {3148,3148, 35, 0, 180, 40,0 }, + {3149,3149, 35, 0, 40000, 0,0 }, + {3150,3150, 0, 0, 40000, 0,0 }, + {3151,3151, 0, 0, 4900, 240,0 }, + {3152,3152, 0, 0, 3480, 80,0 }, + {3153,3153, 0, 0, 3586, 86,0 }, + {3154,3154, 0, 0, 4626, 633,0 }, + {3155,3155, 0, 0, 4293, 2286,0 }, + {3156,3156, 0, 0, 13653, 0,0 }, + {3157,3157, 0, 0, 1206, 426,0 }, + {3158,3158, 0, 0, 653, 426,0 }, + {3159,3159, 0, 0, 40000, 0,0 }, + {3160,3160, 0, 0, 4633, 633,0 }, + {3161,3161, 0, 0, 40000, 73,0 }, + {3162,3162, 0, 0, 40000, 60,0 }, + {3163,3163, 0, 0, 40000, 146,0 }, + {3164,3164, 0, 0, 40000, 73,0 }, + {3165,3165, 0, 0, 40000, 73,0 }, + {3166,3166, 0, 0, 40000, 0,0 }, + {3167,3167, 0, 0, 40000, 66,0 }, + {3168,3168, 0, 0, 3680, 1180,0 }, + {3169,3169, 0, 0, 2406, 846,0 }, + {3170,3170, 0, 0, 1560, 73,0 }, + {3171,3171, 0, 0, 1946, 226,0 }, + {3172,3172, 0, 0, 4333, 13,0 }, + {3173,3173, 0, 0, 40000, 0,0 }, + {3174,3174, 0, 0, 40000, 0,0 }, + {3175,3175, 0, 0, 40000, 66,0 }, + {3176,3176, 0, 0, 40000, 180,0 }, + {3177,3177, 0, 0, 15380, 80,0 }, + {3178,3178, 0, 0, 18213, 73,0 }, + {3179,3179, 0, 0, 1706, 0,0 }, + {3180,3180, 0, 0, 5733, 1266,0 }, + {3181,3181, 0, 0, 40000, 0,0 }, + {3182,3182, 0, 0, 40000, 366,0 }, + {3183,3183, 0, 0, 40000, 66,0 }, + {3184,3184, 0, 0, 4786, 73,0 }, + {3185,3185, 0, 0, 5660, 720,0 }, + {3186,3186, 0, 0, 1293, 406,0 }, + {3187,3187, 0, 0, 40000, 0,0 }, + {3188,3188, 0, 0, 2686, 233,0 }, + {3189,3189, 0, 0, 40000, 0,0 }, + {3190,3190, 0, 0, 40000, 73,0 }, + {3191,3191, 0, 0, 40000, 0,0 }, + {3192,3192, 0, 0, 40000, 73,0 }, + {3193,3193, 0, 0, 40000, 0,0 }, + {3194,3194, 0, 0, 3920, 73,0 }, + {3195,3195, 0, 0, 40000, 73,0 }, + {3196,3196, 0, 0, 40000, 66,0 }, + {3197,3197, 0, 0, 40000, 80,0 }, + {3198,3198, 0, 0, 40000, 86,0 }, + {3199,3199, 0, 0, 40000, 60,0 }, + {3200,3200, 0, 0, 40000, 0,0 }, + {3201,3201, 0, 0, 40000, 353,0 }, + {3202,3202, 0, 0, 3920, 73,0 }, + {3203,3203, 0, 0, 5833, 813,0 }, + {3204,3204, 0, 0, 40000, 60,0 }, + {3205,3205, 0, 0, 40000, 73,0 }, + {3206,3206, 0, 0, 1400, 406,0 }, + {3207,3207, 0, 0, 40000, 66,0 }, + {3208,3208, 0, 0, 9066, 2220,0 }, + {3209,3209, 0, 0, 1473, 773,0 }, + {3210,3210, 0, 0, 40000, 120,0 }, + {3211,3211, 0, 0, 40000, 306,0 }, + {3212,3212, 0, 0, 9306, 3013,0 }, + {3213,3213, 0, 0, 40000, 60,0 }, + {3214,3214, 0, 0, 40000, 73,0 }, + {3215,3215, 0, 0, 40000, 73,0 }, + {3216,3216, 0, 0, 40000, 453,0 }, + {3217,3217, 0, 0, 40000, 3460,0 }, + {3218,3218, 0, 0, 40000, 453,0 }, + {3219,3219, 0, 0, 40000, 40,0 }, + {3220,3220, 0, 0, 40000, 3926,0 }, + {3221,3221, 0, 0, 40000, 4506,0 }, + {3222,3222, 0, 0, 4646, 646,0 }, + {3223,3223, 0, 0, 773, 100,0 }, + {3224,3224, 0, 0, 40000, 73,0 }, + {3225,3225, 0, 0, 40000, 173,0 }, + {3226,3226, 0, 0, 1606, 653,0 }, + {3227,3227, 0, 0, 2353, 806,0 }, + {3228,3228, 0, 0, 980, 360,0 }, + {3229,3229, 0, 0, 1193, 413,0 }, + { 499, 499, 0, 0, 266, 0,0 }, + {3230,3230, 0, 0, 973, 360,0 }, + {3231,3231, 0, 0, 273, 53,0 }, + {3232,3232, 0, 0, 726, 220,0 }, + {3233,3233, 0, 0, 19933, 6093,0 }, + {3234,3234, 0, 0, 40000, 0,0 }, + { 403, 403, 0, 0, 40000, 73,0 }, + {3235,3235, 0, 0, 4966, 233,0 }, + {3236,3236, 0, 0, 4946, 240,0 }, + {3237,3237, 0, 0, 4946, 233,0 }, + {3238,3238, 0, 0, 4640, 1613,0 }, + {3239,3239, 0, 0, 2360, 806,0 }, + {3240,3240, 0, 0, 4466, 200,0 }, + {3241,3241, 0, 0, 40000, 73,0 }, + {3242,3242, 0, 0, 40000, 73,0 }, + {3243,3243, 0, 0, 40000, 73,0 }, + {3244,3244, 0, 0, 40000, 73,0 }, + {3245,3245, 0, 0, 40000, 240,0 }, + {3246,3246, 0, 0, 40000, 226,0 }, + {3247,3247, 0, 0, 40000, 233,0 }, + {3248,3248, 0, 0, 40000, 240,0 }, + {3249,3249, 0, 0, 4306, 1253,0 }, + {3250,3250, 0, 0, 3873, 1206,0 }, + {3251,3251, 0, 0, 4640, 633,0 }, + {3252,3252, 0, 0, 1233, 80,0 }, + {3253,3253, 0, 0, 1233, 26,0 }, + {3254,3254, 0, 0, 1233, 26,0 }, + {3255,3255, 0, 0, 4573, 1253,0 }, + {3256,3256, 0, 0, 3793, 1240,0 }, + {3257,3257, 0, 0, 40000, 73,0 }, + {3258,3258, 0, 0, 40000, 73,0 }, + {3259,3259, 0, 0, 40000, 140,0 }, + {3260,3260, 0, 0, 40000, 146,0 }, + {3261,3261, 0, 0, 40000, 80,0 }, + {3262,3262, 0, 0, 5953, 200,0 }, + {3263,3263, 0, 0, 5926, 200,0 }, + {3264,3264, 0, 0, 5866, 26,0 }, + {3265,3265, 0, 0, 18573, 6153,0 }, + {3266,3266, 0, 0, 40000, 2093,0 }, + {3267,3267, 0, 0, 40000, 73,0 }, + {3268,3268, 0, 0, 18626, 1553,0 }, + {3269,3269, 0, 0, 40000, 1820,0 }, + {3270,3270, 0, 0, 40000, 500,0 }, + {3271,3271, 0, 0, 18206, 5900,0 }, + {3272,3272, 0, 0, 14200, 93,0 }, + {3273,3273, 0, 0, 40000, 2873,0 }, + {3274,3274, 0, 0, 14960, 4913,0 }, + {3275,3275, 0, 0, 40000, 86,0 }, + {3276,3276, 0, 0, 40000, 826,0 }, + {3277,3277, 0, 0, 40000, 200,0 }, + {3278,3278, 0, 0, 40000, 340,0 }, + {3279,3279, 0, 0, 13220, 2500,0 }, + {3280,3280, 0, 0, 40000, 100,0 }, + {3281,3281, 0, 0, 40000, 1026,0 }, + {3282,3282, 0, 0, 40000, 366,0 }, + {3283,3283, 0, 0, 40000, 386,0 }, + {3284,3284, 0, 0, 40000, 0,0 }, + {3285,3285, 0, 0, 40000, 0,0 }, + {3286,3286, 0, 0, 40000, 140,0 }, + {3287,3287, 0, 0, 40000, 53,0 }, + {3288,3288, 0, 0, 40000, 120,0 }, + {3289,3289, 0, 0, 8866, 1366,0 }, + {3290,3290, 0, 0, 4193, 1400,0 }, + {3291,3291, 0, 0, 8353, 673,0 }, + {3292,3292, 0, 0, 8353, 673,0 }, + {3293,3293, 0, 0, 8400, 593,0 }, + {3294,3294, 0, 0, 8440, 666,0 }, + {3295,3295, 0, 0, 9600, 1580,0 }, + {3296,3296, 0, 0, 40000, 46,0 }, + {3297,3297, 0, 0, 40000, 0,0 }, + {3298,3298, 0, 0, 1653, 93,0 }, + {3299,3299, 0, 0, 2706, 73,0 }, + {3300,3300, 0, 0, 11680, 26,0 }, + {3301,3301, 0, 0, 6500, 340,0 }, + {3302,3302, 0, 0, 40000, 0,0 }, + {3303,3303, 0, 0, 40000, 0,0 }, + {3304,3304, 0, 0, 40000, 73,0 }, + {3305,3305, 0, 0, 40000, 73,0 }, + {3306,3306, 0, 0, 40000, 73,0 }, + {3307,3307, 0, 0, 40000, 73,0 }, + {3308,3308, 0, 0, 40000, 73,0 }, + {3309,3309, 0, 0, 40000, 73,0 }, + {3310,3310, 0, 0, 40000, 73,0 }, + {3311,3311, 0, 0, 40000, 73,0 }, + {3312,3312, 0, 0, 40000, 73,0 }, + {3313,3313, 0, 0, 40000, 133,0 }, + {3314,3314, 0, 0, 40000, 126,0 }, + {3315,3315, 0, 0, 40000, 73,0 }, + {3316,3316, 0, 0, 40000, 73,0 }, + {3317,3317, 0, 0, 40000, 73,0 }, + {3318,3318, 0, 0, 40000, 200,0 }, + {3319,3319, 0, 0, 40000, 133,0 }, + {3320,3320, 0, 0, 40000, 0,0 }, + {3321,3321, 0, 0, 40000, 240,0 }, + {3322,3322, 0, 0, 40000, 220,0 }, + {3323,3323, 0, 0, 40000, 226,0 }, + {3324,3324, 0, 0, 40000, 100,0 }, + {3325,3325, 0, 0, 40000, 140,0 }, + {3326,3326, 0, 0, 40000, 0,0 }, + {3327,3327, 0, 0, 40000, 426,0 }, + {3328,3328, 0, 0, 40000, 426,0 }, + {3329,3329, 0, 0, 3680, 1220,0 }, + {3330,3330, 0, 0, 40000, 533,0 }, + {3331,3331, 0, 0, 40000, 813,0 }, + {3332,3332, 0, 0, 14506, 4706,0 }, + {3333,3333, 0, 0, 766, 420,0 }, + {3334,3334, 0, 0, 40000, 1566,0 }, + {3335,3335, 0, 0, 40000, 120,0 }, + {3336,3336, 0, 0, 40000, 2380,0 }, + {3337,3337, 0, 0, 5666, 300,0 }, + {3338,3338, 0, 0, 40000, 73,0 }, + {3339,3339, 0, 0, 40000, 2513,0 }, + {3340,3340, 0, 0, 1260, 826,0 }, + {3341,3341, 0, 0, 2420, 413,0 }, + {3342,3342, 0, 0, 626, 240,0 }, + {3343,3343, 0, 0, 273, 60,0 }, + {3344,3344, 0, 0, 540, 20,0 }, + {3345,3345, 0, 0, 540, 20,0 }, + {3346,3346, 0, 0, 540, 20,0 }, + {3347,3347, 0, 0, 1153, 760,0 }, + {3348,3348, 0, 0, 40000, 100,0 }, + {3349,3349, 0, 0, 7326, 2380,0 }, + {3350,3350, 0, 0, 40000, 4426,0 }, + {3351,3351, 0, 0, 7413, 2493,0 }, + {3352,3352, 0, 0, 253, 20,0 }, + {3353,3353, 0, 0, 246, 33,0 }, + {3354,3354, 0, 0, 286, 13,0 }, + {3355,3355, 0, 0, 953, 13,0 }, + {3356,3356, 0, 0, 293, 20,0 }, + { 142, 142, 20, 0, 1893, 620,0 }, + {3357,1451, 0, 4, 2373, 780,0 }, + {3358,3359, 0, 4, 9260, 246,0 }, + {3360,1455, 0, 4, 40000, 0,0 }, + {3361,1463, 0, 4, 40000, 266,0 }, + { 225,3362, 0, 4, 7993, 100,0 }, + {3363,1545, 0, 4, 293, 86,0 }, + {3364,1547, 0, 4, 40000, 180,0 }, + {3365,3366, 39, 4, 66, 0,0 }, + {3367, 368, 58, 4, 173, 0,0 }, + {3368,1551, 48, 4, 520, 200,0 }, + {3368,3033, 49, 4, 53, 0,0 }, + {3368,3033, 51, 4, 53, 0,0 }, + {3368,3033, 54, 4, 60, 0,0 }, + {3368,3033, 57, 4, 60, 0,0 }, + {3368,3033, 60, 4, 60, 0,0 }, + {3369,3370, 70, 4, 840, 0,0 }, + {1564,1565, 80, 4, 220, 0,0 }, + {3371,1571, 44, 4, 420, 0,0 }, + {3372,3372, 0, 0, 8366, 666,0 }, + {3373,3373, 0, 0, 8366, 666,0 }, + {3374,3374, 0, 0, 3773, 73,0 }, + {3375,3375, 0, 0, 8366, 666,0 }, + {3376,3376, 0, 0, 4693, 26,0 }, + {3377,3377, 0, 0, 7400, 80,0 }, + {3378,3378, 0, 0, 3586, 80,0 }, + {3379,3379, 0, 0, 8366, 666,0 }, + {3380,3380, 0, 0, 3786, 1240,0 }, + {3381,3381, 0, 0, 9013, 1466,0 }, + {3382,3382, 0, 0, 1200, 73,0 }, + {3383,3383, 0, 0, 8146, 1446,0 }, + {3384,3384, 0, 0, 3660, 1206,0 }, + {3385,3385, 0, 0, 200, 100,0 }, + {3386,3386, 0, 0, 40000, 0,0 }, + {3387,3387, 0, 0, 1213, 426,0 }, + {3388,3388, 0, 0, 40000, 2573,0 }, + {3389,3389, 0, 0, 40000, 3446,0 }, + {3390,3390, 0, 0, 40000, 333,0 }, + {3391,3391, 0, 0, 40000, 73,0 }, + {3392,3392, 0, 0, 40000, 93,0 }, + {3393,3393, 0, 0, 40000, 73,0 }, + {3394,3394, 0, 0, 40000, 73,0 }, + {3395,3395, 0, 0, 40000, 73,0 }, + {3396,3396, 0, 0, 2193, 413,0 }, + {3397,3397, 0, 0, 14606, 2886,0 }, + {3398,3398, 0, 0, 10626, 4520,0 }, + {3399,3399, 0, 0, 2413, 100,0 }, + {3400,3400, 0, 0, 3593, 1140,0 }, + {3401,3401, 0, 0, 40000, 146,0 }, + {3402,3402, 0, 0, 40000, 86,0 }, + {3403,3403, 0, 0, 40000, 86,0 }, + {3404,3404, 0, 0, 9366, 106,0 }, + {3405,3405, 0, 0, 40000, 73,0 }, + {3406,3406, 0, 0, 40000, 0,0 }, + {3407,3407, 0, 0, 40000, 0,0 }, + {3408,3408, 0, 0, 1626, 400,0 }, + {3409,3409, 0, 0, 4473, 2933,0 }, + {3410,3410, 0, 0, 40000, 66,0 }, + {3411,3411, 0, 0, 40000, 0,0 }, + {3412,3412, 0, 0, 40000, 253,0 }, + {3413,3413, 0, 0, 40000, 233,0 }, + {3414,3414, 0, 0, 40000, 346,0 }, + {3415,3415, 0, 0, 1966, 26,0 }, + {3416,3416, 0, 0, 40000, 366,0 }, + {3417,3417, 0, 0, 2266, 386,0 }, + {3418,3418, 0, 0, 40000, 0,0 }, + {3419,3419, 0, 0, 2313, 766,0 }, + {3420,3420, 0, 0, 40000, 340,0 }, + {3421,3421, 0, 0, 40000, 346,0 }, + {3422,3422, 0, 0, 40000, 340,0 }, + {3423,3423, 0, 0, 40000, 353,0 }, + {3424,3424, 0, 0, 40000, 353,0 }, + {3425,3425, 0, 0, 40000, 226,0 }, + {3426,3426, 0, 0, 40000, 73,0 }, + {3427,3427, 0, 0, 940, 253,0 }, + {3428,3428, 0, 0, 40000, 73,0 }, + {3429,3429, 0, 0, 40000, 80,0 }, + {3430,3430, 0, 0, 40000, 240,0 }, + {3431,3431, 0, 0, 40000, 80,0 }, + {3432,3432, 0, 0, 40000, 73,0 }, + {3433,3433, 0, 0, 40000, 73,0 }, + {3434,3434, 0, 0, 40000, 73,0 }, + {3435,3435, 0, 0, 40000, 73,0 }, + {3436,3436, 0, 0, 40000, 73,0 }, + {3437,3437, 0, 0, 40000, 73,0 }, + {3438,3438, 0, 0, 40000, 73,0 }, + {3439,3439, 0, 0, 40000, 73,0 }, + {3440,3440, 0, 0, 40000, 73,0 }, + {3441,3441, 0, 0, 40000, 73,0 }, + {3442,3442, 0, 0, 40000, 66,0 }, + {3443,3443, 0, 0, 40000, 73,0 }, + {3444,3444, 0, 0, 40000, 80,0 }, + {3445,3445, 0, 0, 40000, 66,0 }, + {3446,3446, 0, 0, 40000, 66,0 }, + {3447,3447, 0, 0, 40000, 66,0 }, + {3448,3448, 0, 0, 40000, 66,0 }, + {3449,3449, 0, 0, 40000, 80,0 }, + {3450,3450, 0, 0, 40000, 353,0 }, + {3451,3451, 0, 0, 40000, 0,0 }, + {3452,3452, 0, 0, 18440, 100,0 }, + {3453,3453, 0, 0, 18086, 100,0 }, + {3454,3454, 0, 0, 266, 66,0 }, + {3455,3455, 0, 0, 40000, 80,0 }, + {3456,3456, 0, 0, 40000, 100,0 }, + {3457,3457, 0, 0, 40000, 80,0 }, + {3458,3458, 0, 0, 40000, 120,0 }, + {3459,3459, 0, 0, 40000, 93,0 }, + {3460,3460, 0, 0, 40000, 233,0 }, + {3461,3461, 0, 0, 40000, 0,0 }, + {3462,3462, 0, 0, 40000, 86,0 }, + {3463,3463, 0, 0, 40000, 820,0 }, + {3464,3464, 0, 0, 40000, 4986,0 }, + {3465,3465, 0, 0, 40000, 146,0 }, + {3466,3466, 0, 0, 40000, 100,0 }, + {3467,3467, 0, 0, 40000, 3346,0 }, + {3468,3468, 0, 0, 40000, 660,0 }, + {3469,3469, 0, 0, 40000, 366,0 }, + {3470,3470, 0, 0, 40000, 1480,0 }, + {3471,3471, 0, 0, 40000, 646,0 }, + {3472,3472, 0, 0, 40000, 2673,0 }, + {3473,3473, 0, 0, 40000, 2500,0 }, + {3474,3474, 0, 0, 40000, 2513,0 }, + {3475,3475, 0, 0, 40000, 66,0 }, + {3476,3476, 0, 0, 9600, 1580,0 }, + {3477,3477, 0, 0, 40000, 46,0 }, + {3478,3478, 0, 0, 10673, 100,0 }, + {3479,3479, 0, 0, 2333, 800,0 }, + {3480,3480, 0, 0, 3673, 1200,0 }, + {3481,3481, 0, 0, 40000, 73,0 }, + {3482,3482, 0, 0, 40000, 146,0 }, + {3483,3483, 0, 0, 40000, 73,0 }, + {3484,3484, 0, 0, 2266, 726,0 }, + {3485,3485, 0, 0, 333, 140,0 }, + {3486,3486, 0, 0, 2286, 746,0 }, + {3487,3487, 0, 0, 293, 126,0 }, + {3488,3488, 0, 0, 3700, 1213,0 }, + {3489,3489, 0, 0, 3773, 1186,0 }, + {3490,3490, 0, 0, 3646, 1200,0 }, + {3491,3491, 0, 0, 3020, 73,0 }, + {3492,3492, 0, 0, 786, 273,0 }, + {3493,3493, 0, 0, 40000, 146,0 }, + {3494,3494, 0, 0, 40000, 3093,0 }, + {3495,3495, 0, 0, 273, 60,0 }, + {3496,3496, 0, 0, 40000, 73,0 }, + {3497,3497, 0, 0, 40000, 73,0 }, + {3498,3498, 0, 0, 40000, 3093,0 }, + {3499,3499, 0, 0, 40000, 240,0 }, + {3500,3500, 0, 2, 6, 0,0 }, + { 739, 739, 46, 0, 220, 33,0 }, + {3501,3501, 47, 0, 973, 93,0 }, + {3502,3502, 64, 0, 126, 66,0 }, + {3503,3503, 40, 0, 340, 146,0 }, + {3504,3504, 48, 0, 100, 0,0 }, + {3505,3505, 48, 0, 286, 133,0 }, + {3506,3506, 46, 0, 466, 166,0 }, + {3507,3507,111, 0, 226, 113,0 }, + {3508,3508, 49, 0, 473, 166,0 }, + {3509,3509, 56, 0, 126, 40,0 }, + {3510,3510, 52, 0, 520, 206,0 }, + {3511,3511, 96, 0, 1346, 473,0 }, + {3510,3510, 54, 0, 513, 206,0 }, + {3512,3512, 57, 0, 973, 266,0 }, + {3513,3513, 82, 0, 1580, 553,0 }, + {3510,3510, 60, 0, 506, 200,0 }, + {3514,3514, 60, 0, 1886, 646,0 }, + {3515,3515, 92, 0, 1026, 520,0 }, + {3516,3516, 60, 0, 180, 93,0 }, + {3517,3517, 58, 0, 213, 213,0 }, + {3518,3518, 22, 0, 2300, 766,0 }, + {3519,3519, 60, 0, 1873, 653,0 }, + {3520,3520, 72, 0, 260, 93,0 }, + {3521,3521, 77, 0, 253, 93,0 }, + {3522,3522, 70, 0, 206, 93,0 }, + {3523,3523, 75, 0, 173, 93,0 }, + {3524,3524, 69, 0, 406, 113,0 }, + {3525,3525, 59, 0, 380, 160,0 }, + {3526,3526, 48, 0, 373, 40,0 }, + {3527,3527, 89, 0, 433, 180,0 }, + {3528,3528, 84, 0, 813, 180,0 }, + {3529,3529, 33, 0, 240, 53,0 }, + {3530,3530, 55, 0, 220, 86,0 }, + {3531,3531, 58, 0, 526, 200,0 }, + {3532,3532, 52, 0, 526, 193,0 }, + {3533,3533, 57, 0, 166, 80,0 }, + {3534,3534, 57, 0, 240, 100,0 }, + {3535,3535, 85, 0, 220, 113,0 }, + {3536,3536, 68, 0, 173, 93,0 }, + {3536,3536, 61, 0, 220, 113,0 }, + {3537,3537, 64, 0, 346, 53,0 }, + {3538,3538, 44, 0, 1080, 346,0 }, + {3539,3539,100, 0, 193, 20,0 }, + {3540,3540,100, 0, 793, 26,0 }, + {3541,3541, 0, 0, 14166, 320,0 }, + {3542,3542, 0, 0, 3873, 1613,0 }, + {3543,3543, 0, 0, 3586, 86,0 }, + {3544,3544, 0, 0, 7406, 2486,0 }, + {3545,3545, 0, 0, 4640, 1560,0 }, + {3546,3546, 0, 0, 446, 440,0 }, + {3547,3547, 0, 0, 9253, 3100,0 }, + {3548,3548, 0, 0, 4646, 646,0 }, + {3549,3549, 0, 0, 40000, 66,0 }, + {3550,3550, 0, 0, 40000, 73,0 }, + {3551,3551, 0, 0, 40000, 113,0 }, + {3552,3552, 0, 0, 40000, 73,0 }, + {3553,3553, 0, 0, 40000, 73,0 }, + {3554,3554, 0, 0, 40000, 0,0 }, + {3555,3555, 0, 0, 40000, 60,0 }, + {3556,3556, 0, 0, 3673, 1206,0 }, + {3557,3557, 0, 0, 3706, 1293,0 }, + {3558,3558, 0, 0, 5693, 1126,0 }, + {3559,3559, 0, 0, 2406, 846,0 }, + {3560,3560, 0, 0, 40000, 66,0 }, + {3561,3561, 0, 0, 40000, 73,0 }, + {3562,3562, 0, 0, 4333, 13,0 }, + {3563,3563, 0, 0, 3700, 66,0 }, + {3564,3564, 0, 0, 40000, 0,0 }, + {3565,3565, 0, 0, 3713, 1260,0 }, + {3566,3566, 0, 0, 1140, 126,0 }, + {3567,3567, 0, 0, 40000, 186,0 }, + {3568,3568, 0, 0, 40000, 0,0 }, + {3569,3569, 0, 0, 14400, 6,0 }, + {3570,3570, 0, 0, 14580, 66,0 }, + {3571,3571, 0, 0, 40000, 73,0 }, + {3572,3572, 0, 0, 40000, 353,0 }, + {3573,3573, 0, 0, 40000, 0,0 }, + {3574,3574, 0, 0, 40000, 173,0 }, + {3575,3575, 0, 0, 1833, 600,0 }, + {3576,3576, 0, 0, 40000, 0,0 }, + {3577,3577, 0, 0, 40000, 206,0 }, + {3578,3578, 0, 0, 40000, 46,0 }, + {3579,3579, 0, 0, 40000, 73,0 }, + {3580,3580, 0, 0, 9166, 2900,0 }, + {3581,3581, 0, 0, 5640, 680,0 }, + {3582,3582, 0, 0, 640, 220,0 }, + {3583,3583, 0, 0, 40000, 53,0 }, + {3584,3584, 0, 0, 40000, 26,0 }, + {3585,3585, 0, 0, 40000, 0,0 }, + {3586,3586, 0, 0, 40000, 66,0 }, + {3587,3587, 0, 0, 40000, 60,0 }, + {3588,3588, 0, 0, 40000, 0,0 }, + {3589,3589, 0, 0, 40000, 73,0 }, + {3590,3590, 0, 0, 40000, 0,0 }, + {3591,3591, 0, 0, 40000, 0,0 }, + {3592,3592, 0, 0, 3780, 73,0 }, + {3593,3593, 0, 0, 40000, 0,0 }, + {3594,3594, 0, 0, 3786, 73,0 }, + {3595,3595, 0, 0, 40000, 73,0 }, + {3596,3596, 0, 0, 40000, 66,0 }, + {3597,3597, 0, 0, 40000, 73,0 }, + {3598,3598, 0, 0, 40000, 53,0 }, + {3599,3599, 0, 0, 40000, 426,0 }, + {3600,3600, 0, 0, 40000, 133,0 }, + {3601,3601, 0, 0, 40000, 66,0 }, + {3602,3602, 0, 0, 40000, 433,0 }, + {3603,3603, 0, 0, 393, 126,0 }, + {3604,3604, 0, 0, 40000, 66,0 }, + {3605,3605, 0, 0, 40000, 353,0 }, + {3606,3606, 0, 0, 3813, 73,0 }, + {3607,3607, 0, 0, 5793, 780,0 }, + {3608,3608, 0, 0, 40000, 73,0 }, + {3609,3609, 0, 0, 40000, 86,0 }, + {3610,3610, 0, 0, 820, 206,0 }, + {3611,3611, 0, 0, 40000, 66,0 }, + {3612,3612, 0, 0, 40000, 200,0 }, + {3613,3613, 0, 0, 18186, 720,0 }, + {3614,3614, 0, 0, 40000, 0,0 }, + {3615,3615, 0, 0, 40000, 493,0 }, + {3616,3616, 0, 0, 40000, 306,0 }, + {3617,3617, 0, 0, 2166, 600,0 }, + {3618,3618, 0, 0, 40000, 73,0 }, + {3619,3619, 0, 0, 40000, 3073,0 }, + {3620,3620, 0, 0, 2333, 413,0 }, + {3621,3621, 0, 0, 14880, 73,0 }, + {3622,3622, 0, 0, 40000, 66,0 }, + {3623,3623, 0, 0, 40000, 73,0 }, + {3624,3624, 0, 0, 40000, 1873,0 }, + {3625,3625, 0, 0, 40000, 446,0 }, + {3626,3626, 0, 0, 40000, 3126,0 }, + {3627,3627, 0, 0, 18446, 6140,0 }, + {3628,3628, 0, 0, 1113, 240,0 }, + {3629,3629, 0, 0, 40000, 3600,0 }, + {3630,3630, 0, 0, 40000, 4726,0 }, + {3631,3631, 0, 0, 40000, 0,0 }, + {3632,3632, 0, 0, 2893, 606,0 }, + {3633,3633, 0, 0, 40000, 0,0 }, + {3634,3634, 0, 0, 40000, 0,0 }, + {3635,3635, 0, 0, 40000, 173,0 }, + {3636,3636, 0, 0, 40000, 60,0 }, + {3637,3637, 0, 0, 40000, 0,0 }, + {3638,3638, 0, 0, 986, 326,0 }, + {3639,3639, 0, 0, 1873, 646,0 }, + {3640,3640, 0, 0, 200, 260,0 }, + {3641,3641, 0, 0, 1180, 393,0 }, + {3642,3642, 0, 0, 266, 0,0 }, + {3643,3643, 0, 0, 313, 126,0 }, + {3644,3644, 0, 0, 406, 253,0 }, + {3645,3645, 0, 0, 1013, 813,0 }, + {3646,3646, 0, 0, 273, 53,0 }, + {3647,3647, 0, 0, 720, 213,0 }, + {3648,3648, 0, 0, 386, 120,0 }, + {3649,3649, 0, 0, 40000, 766,0 }, + {3650,3650, 0, 0, 40000, 66,0 }, + {3651,3651, 0, 0, 40000, 73,0 }, + {3652,3652, 0, 0, 1186, 426,0 }, + {3653,3653, 0, 0, 16720, 240,0 }, + {3654,3654, 0, 0, 8026, 246,0 }, + {3655,3655, 0, 0, 18186, 140,0 }, + {3656,3656, 0, 0, 14566, 200,0 }, + {3657,3657, 0, 0, 7973, 20,0 }, + {3658,3658, 0, 0, 4446, 86,0 }, + {3659,3659, 0, 0, 4473, 100,0 }, + {3660,3660, 0, 0, 8646, 153,0 }, + {3661,3661, 0, 0, 3726, 660,0 }, + {3662,3662, 0, 0, 1893, 653,0 }, + {3663,3663, 0, 0, 1933, 760,0 }, + {3664,3664, 0, 0, 9160, 240,0 }, + {3665,3665, 0, 0, 1133, 100,0 }, + {3666,3666, 0, 0, 633, 233,0 }, + {3667,3667, 0, 0, 9153, 3060,0 }, + {3668,3668, 0, 0, 2166, 406,0 }, + {3669,3669, 0, 0, 40000, 66,0 }, + {3670,3670, 0, 0, 40000, 73,0 }, + {3671,3671, 0, 0, 40000, 73,0 }, + {3672,3672, 0, 0, 40000, 73,0 }, + {3673,3673, 0, 0, 40000, 346,0 }, + {3674,3674, 0, 0, 40000, 353,0 }, + {3675,3675, 0, 0, 40000, 200,0 }, + {3676,3676, 0, 0, 40000, 320,0 }, + {3677,3677, 0, 0, 4646, 100,0 }, + {3678,3678, 0, 0, 4426, 133,0 }, + {3679,3679, 0, 0, 4633, 100,0 }, + {3680,3680, 0, 0, 2266, 133,0 }, + {3681,3681, 0, 0, 2346, 53,0 }, + {3682,3682, 0, 0, 40000, 66,0 }, + {3683,3683, 0, 0, 9686, 173,0 }, + {3684,3684, 0, 0, 14300, 66,0 }, + {3685,3685, 0, 0, 40000, 0,0 }, + {3686,3686, 0, 0, 40000, 0,0 }, + {3687,3687, 0, 0, 40000, 0,0 }, + {3688,3688, 0, 0, 8613, 73,0 }, + {3689,3689, 0, 0, 40000, 0,0 }, + {3690,3690, 0, 0, 40000, 0,0 }, + {3691,3691, 0, 0, 40000, 0,0 }, + {3692,3692, 0, 0, 40000, 0,0 }, + {3693,3693, 0, 0, 40000, 393,0 }, + {3694,3694, 0, 0, 40000, 126,0 }, + {3695,3695, 0, 0, 40000, 120,0 }, + {3696,3696, 0, 0, 40000, 0,0 }, + {3697,3697, 0, 0, 40000, 226,0 }, + {3698,3698, 0, 0, 7420, 1186,0 }, + {3699,3699, 0, 0, 3280, 1726,0 }, + {3700,3700, 0, 0, 3680, 1220,0 }, + {3701,3701, 0, 0, 40000, 480,0 }, + {3702,3702, 0, 0, 40000, 306,0 }, + {3703,3703, 0, 0, 40000, 433,0 }, + {3704,3704, 0, 0, 40000, 133,0 }, + {3705,3705, 0, 0, 40000, 0,0 }, + {3706,3706, 0, 0, 40000, 0,0 }, + {3707,3707, 0, 0, 1166, 380,0 }, + {3708,3708, 0, 0, 40000, 140,0 }, + {3709,3709, 0, 0, 40000, 126,0 }, + {3710,3710, 0, 0, 40000, 100,0 }, + {3711,3711, 0, 0, 40000, 66,0 }, + {3712,3712, 0, 0, 40000, 226,0 }, + {3713,3713, 0, 0, 40000, 133,0 }, + {3714,3714, 0, 0, 40000, 73,0 }, + {3715,3715, 0, 0, 40000, 226,0 }, + {3716,3716, 0, 0, 40000, 100,0 }, + {3717,3717, 0, 0, 40000, 80,0 }, + {3718,3718, 0, 0, 40000, 100,0 }, + {3719,3719, 0, 0, 40000, 73,0 }, + {3720,3720, 0, 0, 40000, 73,0 }, + {3721,3721, 0, 0, 40000, 73,0 }, + {3722,3722, 0, 0, 40000, 126,0 }, + {3723,3723, 0, 0, 40000, 80,0 }, + {3724,3724, 0, 0, 40000, 73,0 }, + {3725,3725, 0, 0, 40000, 86,0 }, + {3726,3726, 0, 0, 40000, 100,0 }, + {3727,3727, 0, 0, 40000, 0,0 }, + {3728,3728, 0, 0, 40000, 126,0 }, + {3729,3729, 0, 0, 40000, 133,0 }, + {3730,3730, 0, 0, 40000, 140,0 }, + {3731,3731, 0, 0, 40000, 73,0 }, + {3732,3732, 0, 0, 40000, 60,0 }, + {3733,3733, 0, 0, 40000, 93,0 }, + {3734,3734, 0, 0, 40000, 80,0 }, + {3735,3735, 0, 0, 40000, 66,0 }, + {3736,3736, 0, 0, 40000, 0,0 }, + {3737,3737, 0, 0, 40000, 220,0 }, + {3738,3738, 0, 0, 40000, 80,0 }, + {3739,3739, 0, 0, 40000, 400,0 }, + {3740,3740, 0, 0, 40000, 1373,0 }, + {3741,3741, 0, 0, 40000, 86,0 }, + {3742,3742, 0, 0, 40000, 1313,0 }, + {3743,3743, 0, 0, 40000, 0,0 }, + {3744,3744, 0, 0, 11486, 593,0 }, + {3745,3745, 0, 0, 40000, 1246,0 }, + {3746,3746, 0, 0, 40000, 140,0 }, + {3747,3747, 0, 0, 14386, 2680,0 }, + {3748,3748, 0, 0, 40000, 653,0 }, + {3749,3749, 0, 0, 2286, 713,0 }, + {3750,3750, 0, 0, 40000, 253,0 }, + {3751,3751, 0, 0, 6933, 406,0 }, + {3752,3752, 0, 0, 40000, 1313,0 }, + {3753,3753, 0, 0, 40000, 1440,0 }, + {3754,3754, 0, 0, 40000, 73,0 }, + {3755,3755, 0, 0, 11100, 420,0 }, + {3756,3756, 0, 0, 6493, 320,0 }, + {3757,3757, 0, 0, 3486, 126,0 }, + {3758,3758, 0, 0, 6620, 2133,0 }, + {3759,3759, 0, 0, 1180, 413,0 }, + {3760,3760, 0, 0, 40000, 73,0 }, + {3761,3761, 0, 0, 40000, 73,0 }, + {3762,3762, 0, 0, 40000, 66,0 }, + {3763,3763, 0, 0, 4580, 413,0 }, + {3764,3764, 0, 0, 340, 146,0 }, + {3765,3765, 0, 0, 1166, 400,0 }, + {3766,3766, 0, 0, 1346, 660,0 }, + {3767,3767, 0, 0, 1260, 393,0 }, + {3768,3768, 0, 0, 3646, 1186,0 }, + {3769,3769, 0, 0, 2713, 400,0 }, + {3770,3770, 0, 0, 1780, 73,0 }, + {3771,3771, 0, 0, 800, 213,0 }, + {3772,3772, 0, 0, 660, 173,0 }, + {3773,3773, 0, 0, 12146, 73,0 }, + {3774,3774, 0, 0, 273, 60,0 }, + {3775,3775, 0, 0, 40000, 73,0 }, + {3776,3776, 0, 0, 380, 53,0 }, + {3777,3777, 0, 0, 40000, 200,0 }, + {3778,3778, 0, 0, 586, 20,0 }, + {3779,3779, 0, 2, 6, 0,0 }, + { 738, 738, 44, 0, 840, 340,0 }, + {3780,3780, 36, 0, 7366, 140,0 }, + {3781,3781, 32, 0, 100, 0,0 }, + {2030,2030, 60, 0, 293, 126,0 }, + {3782,3782, 24, 0, 100, 0,0 }, + {3783,3783, 60, 0, 126, 73,0 }, + {3784,3784, 44, 0, 393, 93,0 }, + { 132, 132, 44, 0, 173, 100,0 }, + {3785,3785, 47, 0, 393, 93,0 }, + { 152, 152, 44, 0, 213, 86,0 }, + {3784,3784, 50, 0, 393, 93,0 }, + { 139, 139, 44, 0, 293, 100,0 }, + {3784,3784, 54, 0, 393, 93,0 }, + {3784,3784, 57, 0, 393, 93,0 }, + {3786,3786, 60, 0, 1900, 666,0 }, + {3784,3784, 60, 0, 393, 93,0 }, + {3787,3787, 60, 0, 1900, 666,0 }, + {3788,3788, 60, 0, 1886, 666,0 }, + {3789,3789, 60, 0, 1866, 653,0 }, + {3790,3790, 60, 0, 1873, 633,0 }, + {3791,3791, 44, 0, 946, 333,0 }, + {2037,2037, 44, 0, 213, 126,0 }, + { 144, 144, 44, 0, 213, 126,0 }, + {2038,2038, 44, 0, 106, 0,0 }, + {3792,3792, 44, 0, 380, 360,0 }, + {3793,3793, 44, 0, 520, 206,0 }, + {3794,3794, 45, 0, 273, 100,0 }, + {3795,3795, 33, 0, 326, 106,0 }, + {3796,3796, 56, 0, 506, 200,0 }, + {3796,3796, 51, 0, 506, 200,0 }, + {3797,3797, 44, 0, 126, 66,0 }, + {3798,3798, 44, 0, 553, 186,0 }, + {3534,3534, 56, 0, 240, 100,0 }, + { 158, 158, 68, 0, 126, 140,0 }, + {3799,3799, 51, 0, 513, 206,0 }, + {3800,3800, 46, 0, 506, 200,0 }, + {3801,3801, 44, 0, 513, 206,0 }, + {3802,3802, 44, 0, 3720, 1260,0 }, + { 152, 152, 45, 0, 220, 80,0 }, + {3803,3803, 0, 0, 40000, 86,0 }, + {3804,3804, 0, 0, 40000, 226,0 }, + {3805,3805, 0, 0, 40000, 73,0 }, + {3806,3806, 0, 0, 40000, 73,0 }, + {3807,3807, 0, 0, 40000, 93,0 }, + {3808,3808, 0, 0, 4653, 660,0 }, + {3809,3809, 0, 0, 6686, 2246,0 }, + {3810,3810, 0, 0, 1180, 413,0 }, + {3811,3811, 0, 0, 966, 293,0 }, + {3812,3812, 0, 0, 1780, 66,0 }, + {3780,3780, 45, 0, 5900, 113,0 }, + {3061,3061, 45, 0, 40000, 0,0 }, + {3813,3813, 60, 0, 126, 226,0 }, + {3781,3781, 60, 0, 93, 0,0 }, + {3814,3814, 44, 0, 393, 86,0 }, + {3815,3815, 57, 0, 166, 80,0 }, + {3816,3816, 56, 0, 240, 100,0 }, + {3817,3817, 60, 0, 113, 0,0 }, + {3818,3818, 60, 0, 113, 0,0 }, + {3517,3517, 45, 0, 213, 213,0 }, + {3819,3819, 0, 0, 4033, 100,0 }, + {3820,3820, 0, 0, 5200, 873,0 }, + {3821,3821, 0, 0, 40000, 0,0 }, + {3822,3822, 0, 0, 10493, 160,0 }, + {3823,3823, 0, 0, 40000, 740,0 }, + {3824,3825, 0, 1, 40000, 366,0.078125 }, + {3826,3826, 0, 0, 40000, 5100,0 }, + {3827,3827, 0, 0, 40000, 766,0 }, + {3828,1172, 0, 1, 40000, 780,0.15625 }, + {3829,3829, 0, 0, 40000, 60,0 }, + {3830,3830, 0, 0, 566, 133,0 }, + {3831,3831, 32, 0, 146, 0,0 }, + {3832,3832, 36, 0, 273, 0,0 }, + {3833,3833, 88, 0, 340, 120,0 }, + {3834,3834, 0, 0, 9006, 240,0 }, + {3835,3835, 0, 0, 9206, 246,0 }, + {3836,3836, 0, 0, 9246, 386,0 }, + {3837,3837, 0, 0, 9440, 220,0 }, + {3838,3838, 0, 0, 8900, 133,0 }, + {3839,3839, 0, 0, 9400, 253,0 }, + {3840,3840, 0, 0, 4613, 420,0 }, + {3841,3841, 0, 0, 9233, 426,0 }, + {3842,3842, 0, 0, 40000, 526,0 }, + {3843,3843, 0, 0, 40000, 640,0 }, + {3844,3844, 0, 0, 40000, 666,0 }, + {3845,3845, 0, 0, 40000, 1053,0 }, + {3846,3846, 0, 0, 40000, 173,0 }, + {3847,3847, 0, 0, 40000, 246,0 }, + {3848,3848, 0, 0, 40000, 226,0 }, + {3849,3849, 0, 0, 4073, 233,0 }, + {3850,3850, 0, 0, 14286, 326,0 }, + {3851,3851, 0, 0, 9233, 146,0 }, + {3852,3852, 0, 0, 4480, 133,0 }, + {3853,3853, 0, 0, 40000, 53,0 }, + {3854,3854, 0, 0, 40000, 126,0 }, + {3855,3855, 0, 0, 40000, 126,0 }, + {3856,3856, 0, 0, 18226, 146,0 }, + {3857,3857, 0, 0, 40000, 326,0 }, + {3858,3858, 0, 0, 40000, 0,0 }, + {3859,3859, 0, 0, 40000, 300,0 }, + {3860,3860, 0, 0, 40000, 0,0 }, + {3861,3861, 0, 0, 40000, 0,0 }, + {3862,3862, 0, 0, 40000, 0,0 }, + {3863,3863, 0, 0, 40000, 140,0 }, + {3864,3864, 0, 0, 40000, 153,0 }, + {3865,3865, 0, 0, 40000, 233,0 }, + {3866,3866, 0, 0, 40000, 186,0 }, + {3867,3867, 0, 0, 40000, 413,0 }, + {3868,3868, 0, 0, 40000, 373,0 }, + {3869,3869, 0, 0, 1246, 440,0 }, + {3870,3870, 0, 0, 4620, 1513,0 }, + {3871,3871, 0, 0, 40000, 433,0 }, + {3872,3872, 0, 0, 40000, 453,0 }, + {3873,3873, 0, 0, 40000, 1440,0 }, + {3874,3874, 0, 0, 40000, 480,0 }, + {3875,3875, 0, 0, 40000, 1360,0 }, + {3876,3876, 0, 0, 40000, 0,0 }, + {3877,3877, 0, 0, 40000, 353,0 }, + {3878,3878, 0, 0, 40000, 86,0 }, + {3879,3879, 0, 0, 40000, 126,0 }, + {3880,3880, 0, 0, 40000, 73,0 }, + {3881,3881, 0, 0, 40000, 80,0 }, + {3882,3882, 0, 0, 40000, 246,0 }, + {3883,3883, 0, 0, 40000, 93,0 }, + {3884,3884, 0, 0, 40000, 120,0 }, + {3885,3885, 0, 0, 40000, 180,0 }, + {3886,3886, 0, 0, 40000, 133,0 }, + {3887,3887, 0, 0, 40000, 133,0 }, + {3888,3888, 0, 0, 40000, 153,0 }, + {3889,3889, 0, 0, 40000, 93,0 }, + {3890,3890, 0, 0, 40000, 140,0 }, + {3891,3891, 0, 0, 40000, 100,0 }, + {3892,3892, 0, 0, 40000, 146,0 }, + {3893,3893, 0, 0, 40000, 126,0 }, + {3894,3894, 0, 0, 40000, 160,0 }, + {3895,3895, 0, 0, 40000, 226,0 }, + {3896,3896, 0, 0, 40000, 140,0 }, + {3897,3897, 0, 0, 40000, 200,0 }, + {3898,3898, 0, 0, 40000, 66,0 }, + {3899,3899, 0, 0, 40000, 446,0 }, + {3900,3900, 0, 0, 40000, 140,0 }, + {3901,3901, 0, 0, 40000, 400,0 }, + {3902,3902, 0, 0, 40000, 373,0 }, + {3903,3903, 0, 0, 40000, 1306,0 }, + {3904,3904, 0, 0, 40000, 186,0 }, + {3905,3905, 0, 0, 40000, 640,0 }, + {3906,3906, 0, 0, 40000, 346,0 }, + {3907,3907, 0, 0, 40000, 140,0 }, + {3908,3908, 0, 0, 40000, 253,0 }, + {3909,3909, 0, 0, 8980, 746,0 }, + {3910,3910, 0, 0, 40000, 1266,0 }, + {3911,3911, 0, 0, 40000, 1306,0 }, + {3912,3912, 0, 0, 7226, 593,0 }, + {3913,3913, 0, 0, 40000, 140,0 }, + {3914,3914, 0, 0, 40000, 220,0 }, + {3915,3915, 0, 0, 40000, 146,0 }, + {3916,3916, 0, 0, 4606, 1506,0 }, + {3917,3917, 0, 0, 40000, 80,0 }, + {3918,3918, 0, 0, 40000, 0,0 }, + {3919,3919, 0, 0, 40000, 0,0 }, + {3920,3920, 0, 0, 613, 226,0 }, + {3921,3921, 0, 0, 9073, 2946,0 }, + {3922,3922, 0, 0, 40000, 73,0 }, + {3923,3923, 0, 0, 3726, 200,0 }, + {3924,3924, 0, 0, 3680, 373,0 }, + {3925,3925, 0, 0, 7113, 186,0 }, + {3926,3926, 0, 0, 2406, 106,0 }, + {3927,3927, 0, 0, 40000, 0,0 }, + {3928,3928, 0, 0, 40000, 253,0 }, + {3929,3929, 0, 0, 40000, 0,0 }, + {3930,3930, 0, 0, 40000, 80,0 }, + {3931,3931, 0, 0, 40000, 86,0 }, + {3932,3932, 0, 0, 18186, 740,0 }, + {3933,3933, 0, 0, 18426, 813,0 }, + { 523, 523, 0, 0, 200, 260,0 }, + {3934,3934, 0, 0, 340, 146,0 }, + {3935,3935, 0, 0, 366, 260,0 }, + {3936,3936, 48, 0, 126, 0,0 }, + {3937,3937, 27, 0, 200, 106,0 }, + {3938,3938, 40, 0, 1073, 800,0 }, + {3939,3939, 48, 0, 100, 0,0 }, + {3938,3938, 45, 0, 933, 666,0 }, + {3940,3940, 48, 0, 140, 333,0 }, + {3938,3938, 47, 0, 933, 666,0 }, + {3941,3941, 48, 0, 1840, 0,0 }, + {3938,3938, 49, 0, 953, 686,0 }, + {3938,3938, 53, 0, 906, 686,0 }, + {3938,3938, 56, 0, 913, 693,0 }, + { 129, 129, 52, 0, 293, 126,0 }, + { 130, 130, 48, 0, 173, 93,0 }, + { 129, 129, 58, 0, 286, 126,0 }, + { 132, 132, 47, 0, 173, 100,0 }, + { 492, 492, 43, 0, 820, 306,0 }, + { 132, 132, 49, 0, 173, 93,0 }, + { 132, 132, 51, 0, 173, 93,0 }, + { 132, 132, 54, 0, 173, 93,0 }, + { 132, 132, 57, 0, 146, 86,0 }, + { 492, 492, 72, 0, 706, 300,0 }, + { 137, 137, 76, 0, 1900, 666,0 }, + { 138, 138, 84, 0, 740, 300,0 }, + { 139, 139, 36, 0, 353, 146,0 }, + { 140, 140, 76, 0, 1886, 680,0 }, + { 141, 141, 84, 0, 220, 113,0 }, + { 135, 135, 83, 0, 1353, 480,0 }, + { 142, 142, 84, 0, 386, 160,0 }, + {3942,3942, 24, 0, 2313, 780,0 }, + { 137, 137, 77, 0, 1893, 660,0 }, + { 144, 144, 60, 0, 213, 0,0 }, + { 145, 145, 65, 0, 180, 146,0 }, + { 146, 146, 59, 0, 173, 93,0 }, + { 147, 147, 51, 0, 266, 213,0 }, + { 148, 148, 45, 0, 513, 200,0 }, + { 149, 149, 71, 0, 246, 26,0 }, + { 150, 150, 60, 0, 500, 193,0 }, + { 151, 151, 58, 0, 513, 200,0 }, + { 152, 152, 53, 0, 220, 86,0 }, + { 153, 153, 64, 0, 113, 40,0 }, + { 154, 154, 71, 0, 840, 300,0 }, + { 156, 156, 61, 0, 166, 80,0 }, + { 158, 158, 48, 0, 173, 213,0 }, + { 159, 159, 69, 0, 126, 140,0 }, + { 160, 160, 68, 0, 126, 140,0 }, + { 161, 161, 63, 0, 326, 113,0 }, + { 162, 162, 74, 0, 860, 286,0 }, + { 163, 163, 60, 0, 386, 160,0 }, + { 164, 164, 80, 0, 1106, 273,0 }, + { 165, 165, 64, 0, 126, 66,0 }, + { 166, 166, 69, 0, 386, 80,0 }, + { 167, 167, 73, 0, 546, 306,0 }, + { 168, 168, 75, 0, 126, 140,0 }, + { 169, 169, 68, 0, 340, 320,0 }, + { 131, 131, 48, 0, 520, 200,0 }, + {3061,3061, 53, 0, 40000, 0,0 }, + {3943,3944, 0, 4, 2153, 0,0 }, + {3945,3946, 0, 4, 9060, 393,0 }, + { 174,3947, 0, 4, 6953, 0,0 }, + {3948,3949, 0, 4, 9386, 140,0 }, + { 9,3950, 0, 4, 1626, 426,0 }, + {3951,3952, 0, 4, 18466, 240,0 }, + {3953,3954, 0, 4, 4666, 1486,0 }, + { 15,3955, 0, 4, 5700, 1986,0 }, + {3956,3957, 0, 4, 40000, 100,0 }, + {3958,3959, 0, 4, 40000, 73,0 }, + {3960,3961, 0, 4, 40000, 73,0 }, + {3962,3963, 0, 4, 40000, 73,0 }, + {3964,3965, 0, 4, 18280, 153,0 }, + {3966,3965, 0, 4, 18686, 160,0 }, + { 31,3967, 0, 4, 40000, 0,0 }, + {3968,3969, 0, 4, 17966, 100,0 }, + {3970,3971, 0, 4, 40000, 66,0 }, + {3972,3971, 0, 4, 40000, 66,0 }, + {3973,3974, 0, 4, 40000, 46,0 }, + {3975,3976, 0, 4, 18693, 106,0 }, + {3977,3976, 0, 4, 18593, 106,0 }, + {3978,3979, 0, 4, 9366, 106,0 }, + {3980,3981, 0, 4, 9120, 226,0 }, + {3982,3983, 0, 4, 40000, 140,0 }, + {3984,3985, 0, 4, 40000, 800,0 }, + { 54,3986, 0, 4, 2520, 706,0 }, + {3987,3988, 0, 4, 40000, 86,0 }, + {3989,3990, 0, 4, 40000, 233,0 }, + {3991, 253, 0, 4, 40000, 66,0 }, + {3992,3992, 0, 0, 40000, 0,0 }, + {3993,3993, 0, 0, 40000, 120,0 }, + {3994,3995, 0, 4, 40000, 80,0 }, + {3996,3997, 0, 4, 40000, 73,0 }, + {3998,3999, 0, 4, 40000, 86,0 }, + {1503,4000, 0, 4, 40000, 93,0 }, + { 88,4001, 0, 4, 40000, 1220,0 }, + {3743,4002, 0, 4, 7706, 1260,0 }, + { 92,4003, 0, 4, 40000, 186,0 }, + { 93,4004, 0, 4, 40000, 813,0 }, + { 94,4005, 0, 4, 7720, 1260,0 }, + { 96,4006, 0, 4, 40000, 2460,0 }, + { 103,4007, 0, 4, 3720, 1240,0 }, + { 104,4008, 0, 4, 3020, 1226,0 }, + { 105,4009, 0, 4, 6086, 2453,0 }, + { 107,4010, 0, 4, 2100, 760,0 }, + { 108,4011, 0, 4, 40000, 73,0 }, + { 110,4012, 0, 4, 40000, 100,0 }, + { 111,4013, 0, 4, 2366, 820,0 }, + {4014,4015, 0, 4, 1026, 326,0 }, + { 115,4016, 0, 4, 1853, 0,0 }, + { 118,4017, 0, 4, 1553, 53,0 }, + { 119,4018, 0, 4, 593, 0,0 }, + { 120,4019, 0, 4, 2293, 1173,0 }, + { 121,4020, 0, 4, 10673, 3000,0 }, + { 123,4021, 0, 4, 7413, 2486,0 }, + { 124,4022, 0, 4, 40000, 1126,0 }, + { 125,4023, 0, 4, 40000, 1546,0 }, + {4024,4024, 35, 0, 706, 266,0 }, + {4025,4026, 38, 1, 273, 106,0 }, + {4027,4028, 38, 1, 366, 133,0 }, + {4029,4030, 48, 1, 280, 133,-1.90625 }, + {4031,4031, 51, 0, 113, 80,0 }, + {4032,4033, 48, 1, 953, 346,-1.90625 }, + {4034,4034, 61, 1, 3200, 540,0.09375 }, + {3369,1557, 70, 4, 833, 0,0 }, + {4035,4036, 79, 1, 1306, 513,0.078125 }, + {4037,4037, 62, 0, 5200, 466,0 }, + {4038,4039, 67, 1, 2153, 1080,0.078125 }, + {4040,4040, 62, 1, 3226, 573,0.09375 }, + {4041,4042, 54, 1, 286, 133,0 }, + {4041,4043, 48, 1, 286, 126,0 }, + { 389, 389, 42, 0, 266, 73,0 }, + {4044,4045, 48, 1, 280, 126,0 }, + {4046,4047, 48, 1, 380, 60,0 }, + {4048,4048, 16, 0, 180, 20,0 }, + {4049,4049, 16, 0, 740, 20,0 }, + {4050,4051, 64, 4, 1366, 0,0 }, + { 844, 844,244, 2, 6, 0,0 }, + { 855, 855,244, 2, 6, 0,0 }, + { 880, 880,232, 0, 253, 80,0 }, + { 882, 882,220, 0, 40000, 266,0 }, + { 887, 887, 35, 0, 133, 46,0 }, + { 884, 884, 35, 0, 233, 80,0 }, + { 885, 885, 35, 0, 226, 86,0 }, + { 886, 886, 35, 0, 113, 0,0 }, + { 361, 361, 35, 0, 286, 73,0 }, + { 767, 767, 35, 0, 3020, 786,0 }, + { 888, 888, 35, 0, 246, 53,0 }, + {2141,2141, 35, 0, 186, 73,0 }, + { 891, 891, 35, 0, 713, 266,0 }, + {2142,2142, 35, 0, 200, 100,0 }, + {2143,2143, 35, 0, 220, 80,0 }, + {2144,2144, 35, 0, 2393, 100,0 }, + {2145,2145, 35, 0, 1980, 813,0 }, + { 376, 376, 35, 0, 1880, 840,0 }, + { 895, 895, 35, 0, 366, 140,0 }, + {2146,2146, 35, 0, 346, 106,0 }, + { 382, 382, 35, 0, 1073, 113,0 }, + {2147,2147, 35, 0, 106, 80,0 }, + { 898, 898, 35, 0, 206, 153,0 }, + { 899, 899, 35, 0, 633, 240,0 }, + { 900, 900, 35, 0, 620, 240,0 }, + { 871, 871, 35, 0, 380, 73,0 }, + { 388, 388, 35, 0, 286, 80,0 }, + { 901, 901, 35, 0, 260, 26,0 }, + { 902, 902, 35, 0, 1093, 73,0 }, + { 903, 903, 35, 0, 126, 73,0 }, + {3500,3500, 35, 2, 6, 0,0 }, + {4052,4052, 0, 0, 14166, 320,0 }, + {4053,4053, 0, 0, 7413, 653,0 }, + {4054,4054, 0, 0, 40000, 146,0 }, + {4055,4055, 0, 0, 40000, 113,0 }, + {4056,4056, 0, 0, 16773, 193,0 }, + {4057,4057, 0, 0, 40000, 73,0 }, + {4058,4058, 0, 0, 40000, 0,0 }, + {4059,4059, 0, 0, 966, 373,0 }, + {4060,4060, 0, 0, 40000, 80,0 }, + {4061,4061, 0, 0, 40000, 80,0 }, + {4062,4062, 0, 0, 18473, 93,0 }, + {4063,4063, 0, 0, 40000, 60,0 }, + {4064,4064, 0, 0, 40000, 73,0 }, + {4065,4065, 0, 0, 40000, 0,0 }, + {4066,4066, 0, 0, 40000, 213,0 }, + {4067,4067, 0, 0, 40000, 66,0 }, + {4068,4068, 0, 0, 1413, 1026,0 }, + {4069,4069, 0, 0, 506, 200,0 }, + {4070,4070, 0, 0, 3793, 1106,0 }, + {4071,4071, 0, 0, 40000, 220,0 }, + {4072,4072, 0, 0, 40000, 46,0 }, + {4073,4073, 0, 0, 40000, 0,0 }, + {4074,4074, 0, 0, 40000, 60,0 }, + {4075,4075, 0, 0, 40000, 0,0 }, + {4076,4076, 0, 0, 40000, 33,0 }, + {4077,4077, 0, 0, 40000, 0,0 }, + {4078,4078, 0, 0, 40000, 146,0 }, + {4079,4079, 0, 0, 40000, 66,0 }, + {4080,4080, 0, 0, 40000, 353,0 }, + {4081,4081, 0, 0, 40000, 66,0 }, + {4082,4082, 0, 0, 40000, 53,0 }, + {4083,4083, 0, 0, 40000, 73,0 }, + {4084,4084, 0, 0, 40000, 66,0 }, + {4085,4085, 0, 0, 40000, 926,0 }, + {4086,4086, 0, 0, 2833, 200,0 }, + { 127, 127, 36, 0, 386, 166,0 }, + {4087,4087, 36, 0, 100, 0,0 }, + {2030,2030, 36, 0, 346, 140,0 }, + {3782,3782, 48, 0, 93, 0,0 }, + {3783,3783, 36, 0, 146, 0,0 }, + {4088,4088, 48, 0, 1886, 653,0 }, + { 132, 132, 69, 0, 126, 66,0 }, + {4088,4088, 52, 0, 1853, 626,0 }, + { 152, 152, 48, 0, 220, 86,0 }, + {4088,4088, 55, 0, 1886, 640,0 }, + { 139, 139, 57, 0, 293, 133,0 }, + {4088,4088, 58, 0, 1860, 633,0 }, + {4088,4088, 60, 0, 1886, 633,0 }, + {4089,4089, 62, 0, 2660, 900,0 }, + {4088,4088, 63, 0, 1880, 646,0 }, + { 134, 134, 70, 0, 966, 360,0 }, + {4090,4090, 70, 0, 973, 346,0 }, + {4091,4091, 53, 0, 1866, 640,0 }, + {3516,3516, 48, 0, 180, 93,0 }, + {4092,4092, 84, 0, 1360, 473,0 }, + {4093,4093, 43, 0, 513, 206,0 }, + {4094,4094, 56, 0, 1353, 480,0 }, + {3791,3791, 24, 0, 1866, 613,0 }, + { 134, 134, 65, 0, 1346, 486,0 }, + { 146, 146, 48, 0, 173, 93,0 }, + { 146, 146, 54, 0, 173, 93,0 }, + {4095,4095, 42, 0, 246, 140,0 }, + {4095,4095, 39, 0, 240, 133,0 }, + {3816,3816, 52, 0, 306, 113,0 }, + {4096,4096, 52, 0, 413, 86,0 }, + { 158, 158, 60, 0, 146, 166,0 }, + { 158, 158, 66, 0, 146, 166,0 }, + { 158, 158, 59, 0, 146, 166,0 }, + {3538,3538, 91, 0, 773, 233,0 }, + {3547,3547,109, 0, 5300, 1786,0 }, + {4097,4097, 79, 0, 560, 313,0 }, + {4098,4098, 0, 0, 10646, 73,0 }, + {4099,4100, 0, 1, 14166, 586,0.03125 }, + {4101,4102, 0, 1, 15553, 546,0.03125 }, + {4103,4104, 0, 1, 11746, 320,0.046875 }, + {4105,4106, 0, 1, 14706, 646,0.15625 }, + {4107,4108, 0, 1, 7320, 100,0.046875 }, + {4109,4110, 0, 1, 40000, 0,0.0625 }, + {4111,4112, 0, 1, 13660, 260,0 }, + {4113,4114, 0, 1, 15026, 133,0 }, + {4115,4116, 0, 1, 40000, 0,2.5e-05 }, + {4117,4118, 0, 1, 4980, 3400,0 }, + {4119,4120, 0, 1, 7840, 2660,0.046875 }, + {4121,4122, 0, 1, 8326, 180,0 }, + {4123,4124, 0, 1, 1093, 140,0 }, + {4125,4126, 0, 1, 2280, 400,0 }, + {4127,4128, 0, 1, 4553, 1486,0.03125 }, + {4129,4129, 0, 1, 40000, 0,0.03125 }, + {4130,4131, 0, 1, 40000, 60,0.15625 }, + {4132,4133, 0, 1, 40000, 93,0.078125 }, + {4134,4135, 0, 1, 40000, 86,0.15625 }, + {4136,4137, 0, 1, 40000, 520,0.03125 }, + {4138,4139, 0, 1, 40000, 140,0.0625 }, + {4140,4141, 0, 1, 40000, 133,0.140625 }, + {4142,4143, 0, 1, 40000, 73,0 }, + {4144,4145, 0, 1, 40000, 346,0.109375 }, + {4146,4147, 0, 1, 3693, 86,0 }, + {4148,4149, 0, 1, 6586, 460,2.5e-05 }, + {4150,4151, 0, 1, 4320, 93,0 }, + {4152,4153, 0, 1, 7346, 126,0.046875 }, + {4154,4155, 0, 1, 3633, 260,0 }, + {4156,4157, 0, 1, 40000, 126,-1.95312 }, + {4158,4159, 0, 1, 40000, 126,-1.9375 }, + {4160,4161, 0, 1, 40000, 46,0.234375 }, + {4162,4163, 0, 1, 40000, 0,0.03125 }, + {4164,4165, 0, 1, 10320, 86,0 }, + {4166,4167, 0, 1, 12933, 133,0 }, + {4168,4169, 0, 1, 11820, 240,0.046875 }, + {4170,4171, 0, 1, 3966, 166,0 }, + {4172,4173, 0, 1, 40000, 0,0 }, + {4174,4174, 0, 0, 2666, 160,0 }, + {4175,4176, 0, 1, 15046, 93,0.078125 }, + {4177,4178, 0, 1, 40000, 100,0 }, + {4179,4179, 0, 0, 40000, 260,0 }, + {4180,4181, 0, 1, 40000, 126,2.5e-05 }, + {4182,4182, 0, 0, 40000, 233,0 }, + {4183,4184, 0, 1, 40000, 440,0.078125 }, + {4185,4186, 0, 1, 2160, 606,0.109375 }, + {4187,4188, 0, 1, 14753, 2400,0.03125 }, + {4189,4190, 0, 1, 7680, 646,0.03125 }, + {4191,4192, 0, 1, 40000, 446,0.0625 }, + {4193,4194, 0, 1, 40000, 866,-0.0625 }, + {4195,4195, 0, 1, 40000, 1220,0.078125 }, + {4196,4196, 0, 1, 40000, 1960,0.0625 }, + {4197,4198, 0, 1, 40000, 433,0.125 }, + {4199,4200, 0, 1, 40000, 140,0.140625 }, + {4201,4202, 0, 1, 40000, 806,0.109375 }, + {4203,4204, 0, 1, 2040, 486,0.125 }, + {4205,4206, 0, 1, 40000, 86,0 }, + {4207,4208, 0, 1, 40000, 80,0.03125 }, + {4209,4209, 0, 0, 40000, 73,0 }, + {4210,4210, 0, 0, 40000, 126,0 }, + {4211,4212, 0, 1, 40000, 400,0.0625 }, + {4213,4214, 0, 1, 40000, 120,0.0625 }, + {4215,4216, 0, 1, 40000, 0,0.09375 }, + {4217,4217, 0, 1, 40000, 0,0.125 }, + {4218,4219, 0, 1, 40000, 186,0 }, + {4220,4220, 0, 0, 40000, 166,0 }, + {4221,4221, 0, 0, 40000, 73,0 }, + {4222,4222, 0, 0, 40000, 60,0 }, + {4223,4224, 0, 1, 40000, 140,0 }, + {4225,4225, 0, 0, 40000, 140,0 }, + {4226,4226, 0, 0, 40000, 66,0 }, + {4227,4228, 0, 1, 40000, 133,0 }, + {4229,4229, 0, 0, 40000, 86,0 }, + {4230,4230, 0, 0, 40000, 73,0 }, + {4231,4231, 0, 0, 40000, 106,0 }, + {4232,4233, 0, 1, 40000, 186,0.03125 }, + {4234,4235, 0, 1, 40000, 86,0.046875 }, + {4236,4237, 0, 1, 40000, 0,0.03125 }, + {4238,4238, 0, 0, 40000, 300,0 }, + {4239,4239, 0, 0, 40000, 66,0 }, + {4240,4241, 0, 1, 40000, 73,0.125 }, + {4242,4243, 0, 1, 40000, 86,0.109375 }, + {4244,4245, 0, 1, 40000, 146,0.109375 }, + {4246,4247, 0, 1, 40000, 66,-0.03125 }, + {4248,4248, 0, 0, 40000, 60,0 }, + {4249,4250, 0, 1, 40000, 213,0.15625 }, + {4251,4252, 0, 1, 40000, 66,0.125 }, + {4253,4254, 0, 1, 40000, 100,0.03125 }, + {4255,4256, 0, 1, 40000, 1513,0.078125 }, + {4257,4258, 0, 1, 40000, 353,0.109375 }, + {4259,4260, 0, 1, 40000, 133,0.078125 }, + {4261,4262, 0, 1, 40000, 746,0.140625 }, + {4263,4264, 0, 1, 40000, 0,0.109375 }, + {4265,4266, 0, 1, 5033, 1606,0.0625 }, + {4267,4268, 0, 1, 40000, 1146,0.09375 }, + {4269,4270, 0, 1, 40000, 1586,0.109375 }, + {4271,4272, 0, 1, 40000, 0,0.09375 }, + {4273,4274, 0, 1, 40000, 1006,0.125 }, + {4275,4275, 0, 1, 2680, 793,0.109375 }, + {4276,4277, 0, 1, 40000, 0,-0.046875 }, + {4278,4279, 0, 1, 9000, 3186,0.125 }, + {4280,4281, 0, 1, 40000, 1073,-0.078125 }, + {4282,4283, 0, 1, 40000, 2093,0.140625 }, + {4284,4285, 0, 1, 40000, 0,0.078125 }, + {4286,4287, 0, 1, 9580, 713,0.03125 }, + {4288,4289, 0, 1, 6286, 380,0 }, + {4290,4291, 0, 1, 2220, 426,0.03125 }, + {4292,4292, 0, 0, 1166, 760,0 }, + {4293,4294, 0, 1, 1186, 240,0 }, + {4295,4296, 0, 1, 40000, 100,0.0625 }, + {4297,4297, 0, 0, 40000, 160,0 }, + {4298,4298, 0, 0, 40000, 120,0 }, + {4299,4299, 0, 0, 8673, 2413,0 }, + {4300,4300, 0, 0, 393, 126,0 }, + {4301,4302, 0, 1, 1220, 393,0.03125 }, + {4303,4303, 0, 0, 246, 93,0 }, + {4304,4305, 0, 1, 1953, 393,0 }, + {4306,4307, 0, 1, 566, 146,0 }, + {4308,4309, 0, 1, 4220, 133,0 }, + {4310,4311, 0, 1, 2873, 73,0.109375 }, + {4312,4312, 0, 0, 613, 60,0 }, + {4313,4314, 0, 1, 40000, 186,0 }, + {4315,4316, 0, 1, 11880, 2993,0 }, + {4317,4317, 0, 0, 1573, 86,0 }, + {4318,4319, 0, 1, 40000, 793,0 }, + {4320,4321, 0, 1, 40000, 173,0 }, + {4322,4323, 0, 1, 40000, 793,0 }, + {4324,4324, 0, 0, 606, 133,0 }, + {4325,4325, 34, 0, 133, 40,0 }, + {4326,4326, 28, 0, 193, 46,0 }, + {4327,4328, 39, 1, 553, 126,0 }, + {4327,4328, 33, 1, 553, 126,0 }, + {4329,4330, 63, 1, 160, 80,0 }, + {4331,4331, 15, 0, 113, 0,0 }, + {4332,4332, 36, 0, 106, 0,0 }, + {4332,4333, 36, 1, 480, 173,0.40625 }, + {4334,4335, 25, 1, 313, 153,0 }, + {4336,4335, 25, 1, 206, 100,0 }, + {4337,4338, 61, 1, 153, 93,0 }, + {4339,4340, 38, 1, 340, 133,0 }, + {4341,4342, 37, 1, 206, 93,0 }, + {4343,4344, 15, 1, 346, 153,0 }, + {4345,4346,100, 1, 146, 0,0.140625 }, + {4347,4348, 19, 1, 553, 200,0 }, + {4349,4349, 48, 0, 180, 86,0 }, + {4350,4351, 15, 1, 333, 153,0 }, + {4352,4353, 12, 1, 340, 146,0 }, + {4354,4355, 11, 1, 346, 146,0 }, + {4356,4357, 61, 1, 2706, 1033,0.09375 }, + {4358,4355, 8, 1, 340, 146,0 }, + {4359,4360, 91, 1, 1166, 366,-0.046875 }, + {4361,4361, 70, 0, 966, 346,0 }, + {4362,4363, 80, 1, 300, 93,0.125 }, + {4364,4364, 58, 0, 206, 53,0 }, + {4365,4357, 62, 1, 2333, 820,0.09375 }, + {4366,4367, 31, 1, 773, 200,0 }, + {4368,4360, 91, 1, 1160, 360,-0.03125 }, + {4369,4370, 41, 1, 373, 113,0 }, + {4371,4372, 35, 1, 406, 126,0 }, + {4373,4374, 29, 1, 146, 106,0 }, + {4375,4376, 41, 1, 400, 126,0 }, + {4375,4376, 37, 1, 400, 126,0 }, + {4377,4378, 54, 1, 286, 133,0 }, + {4377,4379, 48, 1, 286, 126,0 }, + {4380,4381, 77, 1, 193, 93,0 }, + {4382,4383, 72, 1, 200, 93,0 }, + {4384,4384, 40, 0, 513, 0,0 }, + {4385,4385, 38, 0, 200, 20,0 }, + {4386,4386, 36, 0, 620, 20,0 }, + {4387,4388, 60, 1, 120, 80,0 }, + {4388,4389, 60, 1, 380, 80,0 }, + {4390,4390, 73, 0, 166, 33,0 }, + {4391,4392, 68, 1, 153, 40,0 }, + {4393,4394, 18, 1, 200, 80,0 }, + {4395,4396, 18, 1, 253, 73,0 }, + {4397,4397, 90, 0, 193, 20,0 }, + {4398,4398, 90, 0, 793, 40,0 }, + {4399,4400, 64, 1, 373, 73,0.03125 }, + {4401,4402, 80, 1, 406, 153,0.03125 }, + {4403,4404, 64, 1, 1866, 606,0 }, + {4405,4405, 67, 0, 106, 26,0 }, + {4406,4407, 50, 1, 173, 0,0 }, + {4408,4408, 36, 0, 4646, 0,0 }, + {4409,4409, 0, 0, 40000, 86,0 }, + {4410,4410, 0, 0, 40000, 73,0 }, + {4411,4411, 0, 0, 2433, 700,0 }, + {4412,4412, 0, 0, 1233, 26,0 }, + {4413,4413, 0, 0, 40000, 66,0 }, + {4414,4414, 0, 0, 40000, 60,0 }, + {4415,4415, 0, 0, 40000, 60,0 }, + {4416,4416, 0, 0, 40000, 66,0 }, + {4417,4417, 0, 0, 40000, 66,0 }, + {4418,4418, 0, 0, 40000, 0,0 }, + {4418,4418, 73, 0, 40000, 0,0 }, + {4419,4419, 0, 0, 40000, 60,0 }, + {4420,4420, 0, 0, 40000, 60,0 }, + {4421,4421, 0, 0, 7326, 2486,0 }, + {4422,4422, 0, 0, 4886, 1586,0 }, + {4423,4423, 0, 0, 646, 20,0 }, + {4424,4424, 0, 0, 253, 20,0 }, + {4424,4424, 12, 0, 253, 20,0 }, + {4425,4425, 0, 0, 640, 100,0 }, + {4425,4425, 1, 0, 640, 106,0 }, + {4426,4426, 0, 0, 133, 106,0 }, + {4426,4426, 23, 0, 133, 106,0 }, + {4427,4427, 0, 0, 653, 100,0 }, + {4428,4428, 0, 0, 4166, 1546,0 }, + {4429,4429, 0, 0, 40000, 73,0 }, + {4430,4430, 0, 0, 40000, 60,0 }, + {4431,4431, 0, 0, 40000, 53,0 }, + {4432,4432, 0, 0, 40000, 0,0 }, + {4433,4433, 0, 0, 246, 20,0 }, + {4434,4434, 0, 2, 6, 0,0 }, + {4435,4435, 0, 0, 4946, 233,0 }, + {4436,4436, 0, 0, 4946, 233,0 }, + {4437,4437, 0, 0, 4953, 240,0 }, + {4438,4438, 0, 0, 4946, 233,0 }, + {4439,4439, 0, 0, 18233, 46,0 }, + {4440,4440, 0, 0, 2386, 26,0 }, + {4441,4441, 0, 0, 4640, 633,0 }, + {4442,4442, 0, 0, 18466, 100,0 }, + {4443,4443, 0, 0, 18440, 66,-2 }, + {4444,4444, 0, 0, 18440, 6140,-2 }, + {4445,4445, 0, 0, 1206, 433,-2 }, + {4446,4446, 0, 0, 4626, 240,0 }, + {4447,4447, 0, 0, 726, 400,0 }, + {4448,4448, 0, 0, 5866, 73,0 }, + {4449,4449, 0, 0, 40000, 73,0 }, + {4450,4450, 0, 0, 40000, 73,0 }, + {4451,4451, 0, 0, 40000, 73,0 }, + {4452,4452, 0, 0, 40000, 73,0 }, + {4453,4453, 0, 0, 6500, 346,0 }, + {4454,4454, 0, 0, 6506, 346,0 }, + {4455,4455, 0, 0, 40000, 66,-2 }, + {4456,4456, 0, 0, 40000, 66,-2 }, + {4457,4457, 0, 0, 40000, 0,0 }, + {4458,4458, 0, 0, 40000, 46,0 }, + {4459,4459, 0, 0, 40000, 0,0 }, + {4459,4459, 0, 0, 40000, 0,-2 }, + {4460,4460, 0, 0, 2386, 26,0 }, + {4461,4461, 0, 0, 40000, 73,-2 }, + {4462,4462, 0, 0, 5866, 26,-2 }, + {4463,4463, 0, 0, 40000, 133,0 }, + {4464,4464, 0, 0, 40000, 133,0 }, + {4465,4465, 0, 0, 40000, 126,0 }, + {4466,4466, 0, 0, 253, 20,0 }, + {4467,4467, 0, 0, 8866, 1366,0 }, + {4468,4468, 0, 0, 1040, 766,0 }, + {4469,4469, 0, 0, 40000, 146,-2 }, + {4470,4470, 0, 0, 40000, 153,-2 }, + {4471,4471, 0, 0, 40000, 466,-2 }, + {4472,4472, 0, 0, 40000, 66,0 }, + {4473,4473, 0, 0, 2333, 566,0 }, + {4474,4474, 0, 0, 40000, 140,-2 }, + {4475,4475, 0, 0, 40000, 100,-2 }, + {4476,4476, 0, 0, 40000, 226,-2 }, + {4477,4477, 0, 0, 40000, 0,0 }, + {3712,3712, 0, 0, 40000, 226,-2 }, + {4478,4478, 0, 0, 40000, 140,-2 }, + {4479,4479, 0, 0, 40000, 66,0 }, + {4480,4480, 0, 0, 40000, 73,0 }, + {4481,4481, 0, 0, 40000, 73,0 }, + {4482,4482, 0, 0, 40000, 86,-2 }, + {4483,4483, 0, 0, 40000, 80,0 }, + {4484,4484, 0, 0, 40000, 73,-2 }, + {4485,4485, 0, 0, 40000, 80,-2 }, + {4486,4486, 0, 0, 40000, 73,-2 }, + {4487,4487, 0, 0, 40000, 73,0 }, + {4488,4488, 0, 0, 40000, 73,0 }, + {4489,4489, 0, 0, 40000, 93,0 }, + {4490,4490, 0, 0, 40000, 73,0 }, + {4491,4491, 0, 0, 11946, 13,0 }, + {4492,4492, 0, 0, 40000, 73,0 }, + {4462,4462, 0, 0, 5866, 26,0 }, + {4493,4493, 0, 0, 40000, 820,0 }, + {4494,4494, 0, 0, 2153, 873,0 }, + {1221,1221, 0, 0, 40000, 293,0.171875 }, + {4495,4495, 0, 0, 1620, 120,0 }, + {4496,4496, 0, 0, 15120, 93,0 }, + {4497,4497, 0, 0, 14613, 93,0 }, + {4498,4498, 0, 0, 2346, 793,0 }, + {4499,4499, 0, 0, 40000, 2380,0 }, + {4500,4500, 0, 0, 40000, 1280,0 }, + {4501,4501, 0, 0, 40000, 1460,0 }, + {4502,4502, 0, 0, 40000, 2513,0 }, + {4503,4503, 0, 0, 14840, 1266,0 }, + {4504,4504, 0, 0, 4513, 640,0 }, + {4505,4505, 0, 0, 4680, 806,0 }, + {4506,4506, 0, 0, 40000, 100,0 }, + {4507,4507, 0, 0, 40000, 66,0 }, + {4508,4508, 0, 0, 2420, 413,0 }, + {4509,4509, 0, 0, 406, 73,-2 }, + {4510,4510, 0, 0, 1166, 400,0 }, + {4511,4511, 0, 0, 1213, 106,0 }, + {4512,4512, 0, 0, 273, 60,-2 }, + {4513,4513, 0, 0, 40000, 2380,0 }, + {4514,4514, 0, 0, 40000, 440,0 }, + {1261,1261, 0, 0, 40000, 2960,0 }, + {4515,4515, 37, 0, 973, 73,-2 }, + {4516,4516, 48, 0, 106, 0,-2 }, + {4517,4517, 48, 0, 286, 133,-2 }, + {4518,4518, 62, 0, 166, 60,0 }, + {4519,4519, 44, 0, 980, 360,0 }, + {4520,4520, 80, 0, 100, 0,0 }, + {4519,4519, 50, 0, 980, 346,0 }, + {4521,4521, 48, 0, 106, 0,-2 }, + {4519,4519, 55, 0, 973, 360,0 }, + {4522,4522, 61, 0, 513, 20,0 }, + {4519,4519, 58, 0, 966, 353,0 }, + {4519,4519, 63, 0, 973, 353,0 }, + {4523,4523, 71, 0, 1366, 580,0 }, + {4519,4519, 72, 0, 820, 306,0 }, + {4524,4524, 70, 0, 1886, 666,0 }, + {4523,4523, 88, 0, 1353, 560,0 }, + {4525,4525, 76, 0, 1873, 653,0 }, + {4526,4526, 84, 0, 260, 113,0 }, + {4523,4523, 68, 0, 1366, 553,0 }, + {4527,4527, 72, 0, 153, 53,0 }, + {4528,4528, 28, 0, 1193, 413,0 }, + {4524,4524, 81, 0, 1353, 480,0 }, + {4529,4529, 58, 0, 246, 120,-2 }, + {4529,4529, 55, 0, 246, 120,-2 }, + {4529,4529, 44, 0, 246, 120,-2 }, + {4529,4529, 49, 0, 246, 120,-2 }, + {4529,4529, 40, 0, 286, 133,-2 }, + {4530,4530, 55, 0, 740, 560,-2 }, + {4530,4530, 48, 0, 893, 693,-2 }, + {4531,4531, 52, 0, 513, 206,0 }, + {4531,4531, 45, 0, 513, 206,0 }, + {4532,4532, 48, 0, 173, 100,-2 }, + {4533,4533, 48, 0, 120, 266,-2 }, + {4534,4534, 48, 0, 253, 60,-2 }, + {4509,4509, 73, 0, 160, 20,-2 }, + {4509,4509, 68, 0, 160, 20,-2 }, + {4509,4509, 63, 0, 193, 20,-2 }, + {4535,4535,108, 0, 406, 26,0 }, + {4536,4536,108, 0, 740, 26,0 }, }; //Returns total number of generated banks int maxAdlBanks() -{ return 74; +{ return 75; } -const char* const banknames[74] = +const char* const banknames[75] = { "AIL (Star Control 3, Albion, Empire 2, etc.)", "Bisqwit (selection of 4op and 2op)", @@ -9069,15 +9438,16 @@ const char* const banknames[74] = "DMX (Raptor)", "OP3 (Modded GMOPL by Wohlstand)", "SB (Jammey O'Connel's bank)", - "TMB (Default bank of Build Engine)", + "TMB (Default bank of Apgee Sound System)", "WOPL (4op bank by James Alan Nguyen and Wohlstand)", "TMB (Blood)", "TMB (Lee)", "TMB (Nam)", "WOPL (DMXOPL3 bank by Sneakernets)", "EA (Cartooners)", + "WOPL (Apogee IMF 90-ish)", }; -const unsigned short banks[74][256] = +const unsigned short banks[75][256] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -9105,7 +9475,7 @@ const unsigned short banks[74][256] = 232, 233, 234, 235, 236, 237, 238, 239, 71, 72, 240, 241, 242, 243, 244, 245, 246, 247, 248, 82, 249, 250, 251, 86, 252, 253, 254, 255, 91, 92, 256, 257, 258, 259, 260, 98, 99, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 111, 272, 273, 274, 115, 275, 276, 277, 278, 120, 279, 280, 281, 282, 283, 284, + 111, 272, 273, 274, 115, 275, 276, 277, 278, 120, 279, 280, 281, 282, 295, 284, 127, 132, 285, 286, 127, 287, 288, 289, 290, 291, 292, 127, 127, 293, 294, 295, 289, 296, 297, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 318, 320, 318, 321, 318, @@ -9124,86 +9494,86 @@ const unsigned short banks[74][256] = 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 385, 386, 387, 388, 389, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 385, 386, 387, 388, 389, 390, 391, 392, 369, 393, 308, 394, 395, 396, 397, 398, 399, 398, 400, 401, 402, 403, 404, 405, 406, 404, 406, 407, 404, 408, 404, 330, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 341, 342, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 419, 430, 351, 431, 308, 432, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, + 428, 429, 419, 430, 351, 431, 308, 432, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { - 433, 434, 435, 28, 436, 31, 30, 437, 438, 439, 440, 441, 442, 38, 46, 443, + 295, 434, 435, 28, 436, 31, 30, 437, 438, 439, 440, 441, 442, 38, 46, 443, 79, 84, 444, 445, 49, 89, 92, 93, 105, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 119, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 304, 470, 471, 472, 473, + 468, 469, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 304, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 345, 517, 518, 519, 520, - 521, 522, 523, 524, 525, 526, 527, 528, 355, 356, 357, 358, 359, 529, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, + 521, 522, 523, 524, 525, 526, 527, 528, 355, 356, 357, 358, 359, 529, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { - 433, 434, 435, 28, 436, 31, 30, 437, 438, 439, 440, 441, 442, 38, 46, 443, + 295, 434, 435, 28, 436, 31, 30, 437, 438, 439, 440, 441, 442, 38, 46, 443, 79, 84, 444, 445, 49, 89, 92, 93, 105, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 119, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 433, 112, 99, 530, 531, 93, 532, 248, 107, 116, 533, 28, 78, 534, 535, - 536, 79, 94, 38, 33, 115, 537, 538, 539, 540, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 541, 542, 543, 544, 545, 546, 433, 295, + 468, 295, 112, 99, 530, 531, 93, 532, 248, 107, 116, 533, 28, 78, 534, 535, + 536, 79, 94, 38, 33, 115, 537, 538, 539, 540, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 541, 542, 543, 544, 545, 546, 295, 295, 547, 132, 134, 136, 138, 139, 141, 173, 156, 291, 292, 127, 548, 549, 550, 551, - 552, 362, 553, 143, 433, 433, 433, 433, 433, 433, 433, 304, 470, 471, 472, 473, + 552, 362, 553, 143, 295, 295, 295, 295, 295, 295, 295, 304, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 554, 555, 556, 557, 487, 488, 489, 490, 491, 492, 493, 558, 495, 496, 497, 498, 499, 500, 501, 559, 503, 504, 505, 506, 507, 508, 560, 561, 511, 512, 513, 514, 562, 563, 345, 517, 518, 519, 520, - 521, 522, 523, 524, 525, 526, 527, 528, 564, 356, 565, 358, 359, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 295, + 521, 522, 523, 524, 525, 526, 527, 528, 564, 356, 565, 358, 359, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { - 433, 434, 435, 28, 436, 31, 30, 437, 438, 439, 440, 441, 442, 38, 46, 443, + 295, 434, 435, 28, 436, 31, 30, 437, 438, 439, 440, 441, 442, 38, 46, 443, 79, 84, 444, 445, 49, 89, 92, 93, 105, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 119, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 566, 567, 568, 569, + 468, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 566, 567, 568, 569, 570, 34, 571, 572, 437, 51, 52, 84, 573, 574, 575, 576, 577, 85, 530, 90, - 93, 94, 101, 578, 114, 119, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 293, 127, 548, + 93, 94, 101, 578, 114, 119, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 293, 127, 548, 550, 296, 297, 296, 297, 298, 299, 300, 301, 302, 303, 304, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 345, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 355, 356, 357, 358, 359, 360, 361, 362, - 164, 363, 156, 364, 292, 365, 366, 367, 368, 178, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, + 164, 363, 156, 364, 292, 365, 366, 367, 368, 178, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { - 433, 434, 435, 28, 436, 31, 30, 437, 438, 439, 440, 441, 442, 38, 46, 443, + 295, 434, 435, 28, 436, 31, 30, 437, 438, 439, 440, 441, 442, 38, 46, 443, 79, 84, 444, 445, 49, 89, 92, 93, 105, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 119, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 433, 579, 580, 581, 433, 433, 582, 433, 433, 433, 433, 583, 584, 585, 586, - 587, 444, 588, 589, 590, 433, 591, 592, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 577, 566, + 468, 295, 579, 580, 581, 295, 295, 582, 295, 295, 295, 295, 583, 584, 585, 586, + 587, 444, 588, 589, 590, 295, 591, 592, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 577, 566, 437, 90, 460, 28, 593, 594, 595, 596, 31, 597, 598, 28, 441, 442, 567, 530, - 93, 572, 599, 279, 30, 435, 100, 94, 575, 38, 281, 437, 447, 51, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 356, 357, 358, 359, 304, 470, 471, 472, 473, + 93, 572, 599, 279, 30, 435, 100, 94, 575, 38, 281, 437, 447, 51, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 356, 357, 358, 359, 304, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 345, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 355, 600, 601, 602, 127, 548, 296, 603, 604, 550, 605, 606, 362, 607, 135, 608, 361, 609, 610, 611, 612, 507, 146, 613, - 547, 500, 614, 364, 173, 615, 366, 600, 616, 617, 618, 619, 620, 621, 433, 433, + 547, 500, 614, 364, 173, 615, 366, 600, 616, 617, 618, 619, 620, 621, 295, 295, }, { 622, 179, 371, 180, 372, 373, 374, 375, 376, 377, 186, 378, 187, 379, 380, 190, @@ -9231,15 +9601,15 @@ const unsigned short banks[74][256] = 659, 599, 660, 661, 662, 68, 663, 664, 71, 665, 666, 74, 75, 667, 668, 669, 577, 85, 441, 442, 38, 84, 46, 86, 530, 88, 670, 90, 91, 92, 93, 94, 258, 671, 97, 532, 99, 100, 101, 672, 536, 673, 674, 675, 676, 677, 464, 110, - 678, 578, 113, 114, 679, 116, 680, 599, 31, 462, 279, 125, 465, 281, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 681, 682, 683, 500, 503, 614, 684, 685, 296, 552, 550, 605, 600, + 678, 578, 113, 114, 679, 116, 680, 599, 31, 462, 279, 125, 465, 281, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 681, 682, 683, 500, 503, 614, 684, 685, 296, 552, 550, 605, 600, 548, 602, 127, 601, 293, 549, 604, 551, 603, 298, 362, 299, 135, 300, 361, 301, 302, 547, 303, 142, 143, 144, 619, 146, 291, 686, 149, 687, 367, 368, 292, 365, 366, 364, 688, 158, 689, 690, 615, 162, 163, 164, 363, 691, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 692, 693, 694, 695, 696, 697, 698, 699, - 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, 433, + 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { 712, 713, 714, 715, 716, 713, 717, 718, 719, 720, 721, 722, 723, 724, 715, 725, @@ -9250,14 +9620,14 @@ const unsigned short banks[74][256] = 769, 770, 771, 664, 772, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 788, 789, 786, 753, 790, 780, 780, 780, 791, 791, 792, 793, 794, 795, 796, 680, 680, 797, 798, 799, 800, 801, 802, 803, 742, 804, - 805, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, + 805, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 821, 824, 825, 821, 826, 821, 827, 828, 829, 830, 831, 832, - 833, 834, 834, 835, 835, 825, 825, 836, 837, 838, 806, 839, 840, 841, 806, 806, - 842, 843, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, + 833, 834, 834, 835, 835, 825, 825, 836, 837, 838, 295, 839, 840, 841, 295, 295, + 842, 843, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, @@ -9268,14 +9638,14 @@ const unsigned short banks[74][256] = 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 295, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 971, 972, 973, 974, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 971, 972, 973, 974, 975, 310, 976, 977, 978, 974, 979, 980, 981, 982, 983, 984, 983, 985, 986, 987, 988, 989, 990, 325, 989, 325, 991, 989, 992, 989, 330, 993, 994, 995, 996, 997, 998, 999,1000,1001,1002,1003, 340,1004,1005,1006,1007,1008,1009, 310,1010,1011, -1012, 429,1003, 430,1013,1014, 974,1015, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 295, +1012, 429,1003, 430,1013,1014, 974,1015, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { 1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031, @@ -9286,14 +9656,14 @@ const unsigned short banks[74][256] = 1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110, 1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126, 1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 305, 306, 307, 308, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 305, 306, 307, 308, 1143, 425, 311,1144, 393, 308, 394, 395, 396, 397,1145, 399,1145, 400,1146, 402, 403, 404, 405, 406, 404, 406, 407, 404, 408, 404, 330, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 341, 342, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 419, 430, 351, 431, 308, 432, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, + 428, 429, 419, 430, 351, 431, 308, 432, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { 1147,1017,1018,1148,1149,1150,1022, 184,1024,1025,1026,1027,1028,1151,1152,1153, @@ -9304,14 +9674,14 @@ const unsigned short banks[74][256] = 1188,1189,1097,1098,1190,1100,1191,1192,1103,1193,1194,1195,1196,1197,1198,1199, 1111,1200,1201,1202,1203,1116,1204,1205,1119,1206,1207,1122,1123,1124,1125,1208, 1127,1209,1210,1130,1131,1211,1212,1213,1135,1214,1215,1138,1139,1216,1217,1218, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 385, 386, 387, 388, 389, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 385, 386, 387, 388, 389, 390, 391, 392,1219,1219, 308, 394, 395, 396, 397, 398, 399, 398, 400, 401, 402, 403, 404, 405, 406, 404, 406, 407, 404, 408, 404, 330, 409, 410, 411, 412, 413, 414, 415, 416,1220,1221, 419, 420, 341, 342, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 419, 430, 351, 431, 308, 432, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, + 428, 429, 419, 430, 351, 431, 308, 432, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -9344,7 +9714,7 @@ const unsigned short banks[74][256] = 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 312,1349,1350,1351,1352,1353,1354, 319,1355, 320,1356, 321,1357, 1358,1359,1360,1361,1362,1363,1364,1365,1366,1359,1367,1361, 332, 333, 334, 335, - 336,1368,1369, 338, 339, 320,1370,1371,1371,1371,1371,1372,1373,1374,1375,1371, + 336,1368,1369, 338, 339, 320,1370, 295, 295, 295, 295,1372,1373,1374,1375, 295, 347, 348, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, @@ -9362,7 +9732,7 @@ const unsigned short banks[74][256] = 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 312,1349,1350,1351,1352,1382,1354, 319,1355, 320,1356, 321,1357, 1358,1359,1360,1361,1362,1363,1364,1383,1366,1359,1384,1361, 332, 333, 334, 335, - 336,1368,1369, 338, 339, 320,1370,1371,1371,1371,1371,1372,1373,1374,1375,1371, + 336,1368,1369, 338, 339, 320,1370, 295, 295, 295, 295,1372,1373,1374,1375, 295, 347, 348, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, @@ -9380,7 +9750,7 @@ const unsigned short banks[74][256] = 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 312,1349,1350,1351,1352,1353,1354, 319,1355, 320,1356, 321,1357, 1358,1359,1360,1361,1362,1363,1364,1383,1366,1359,1387,1361, 332, 333, 334, 335, - 336,1368,1369, 338, 339, 320,1370,1371,1371,1371,1371,1372,1373,1374,1375,1371, + 336,1368,1369, 338, 339, 320,1370, 295, 295, 295, 295,1372,1373,1374,1375, 295, 347, 348, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, @@ -9447,7 +9817,7 @@ const unsigned short banks[74][256] = 232, 233, 234, 235,1583, 237, 238, 239,1584,1585, 240,1586, 242, 243, 244,1587, 246, 247,1588,1589, 249, 250, 251,1590, 252, 253, 254, 255,1591,1592,1593,1594, 1595, 259,1596,1597,1598,1599,1600,1601, 264, 265, 266, 267, 268, 269, 270, 271, -1602, 272, 273,1603,1604,1605, 276,1606,1607,1608,1609,1610,1611,1612, 283, 284, +1602, 272, 273,1603,1604,1605, 276,1606,1607, 295, 295,1610,1611,1612, 295, 284, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 127, 127,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623, @@ -9556,14 +9926,14 @@ const unsigned short banks[74][256] = 2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2071,2072,2073, 2074,2075,2076,2077,2078,2079,2080, 275,2081,2082,1527,2083,2084,2085,2086,2087, 2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099, 122,2100,2101,2102, -2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103, -2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103, -2103,2103,2103,2104,2105,2106,2107,2108,2109,2110,2111,2110,2112,2113,2114,2113, -2115, 547,2115,2116,2103,2103,2117,2103,2118,2103,2103,2103,2119,2120,2121,2122, -2123,2124,2125,2126,2127, 160, 161, 162, 163,2128,2103,2129,2103,2103,2103,2103, -2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103, -2103,2103,2103,2103, 295,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103, -2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295,2104,2105,2106,2107,2108,2109,2110,2111,2110,2112,2113,2114,2113, +2115, 547,2115,2116, 295, 295,2117, 295,2118, 295, 295, 295,2119,2120,2121,2122, +2123,2124,2125,2126,2127, 160, 161, 162, 163,2128, 295,2129, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { 2130,2130,2130,2130,2130,2130, 727,2131,2132,2133,2134,2135,2136,2137,2138,2139, @@ -9645,7 +10015,7 @@ const unsigned short banks[74][256] = 232, 233, 234, 235,2281, 237, 238, 239,1584,1585,2282,1586, 242, 243, 244,1587, 246, 247,1588,1589, 249, 250, 251,1590,2283, 253, 254, 255,1591,1592,1593,1594, 1595, 259,1596,1597,1598,1599,1600,1601, 264, 265, 266, 267, 268, 269, 270, 271, -1602, 272, 273,1603,1604,1605, 276,1606,1607,1608,1609,1610,1611,1612, 283, 284, +1602, 272, 273,1603,1604,1605, 276,1606,1607, 295, 295,1610,1611,1612, 295, 284, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,2284, 295, 295, 295,2284,2285,2286,1614,1615,2287,2288,1618,1619,1620,1621,1622,1623, @@ -9735,7 +10105,7 @@ const unsigned short banks[74][256] = 232, 233, 234, 235,1583, 237, 238, 239,1584,1585, 240,1586, 242, 243, 244,1587, 246, 247,1588,1589, 249, 250, 251,1590, 252, 253, 254, 255,1591,1592,1593,1594, 1595, 259,1596,1597,1598,1599,1600,1601, 264, 265, 266, 267, 268, 269, 270, 271, -1602, 272, 273,1603,1604,1605, 276,1606,1607,1608,1609,1610,1611,1612, 283, 284, +1602, 272, 273,1603,1604,1605, 276,1606,1607, 295, 295,1610,1611,1612, 295, 284, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,2430,2430,2431,2432,2433,2434,2435,2436,2437,2436,2438,2436,2439, @@ -9771,7 +10141,7 @@ const unsigned short banks[74][256] = 232, 233, 234, 235,1583, 237, 238, 239,1584,1585, 240,1586, 242, 243, 244,1587, 246, 247,1588,1589, 249, 250, 251,1590, 252, 253, 254, 255,1591,1592,1593,1594, 1595, 259,1596,1597,1598,1599,1600,1601, 264, 265, 266, 267, 268, 269, 270, 271, -1602, 272, 273,1603,1604,1605, 276,1606,1607,1608,1609,1610,1611,1612, 283, 284, +1602, 272, 273,1603,1604,1605, 276,1606,1607, 295, 295,1610,1611,1612, 295, 284, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 127, 127,2286,1614,1615,1616,2288,1618,1619,1620,1621,1622,1623, @@ -9811,7 +10181,7 @@ const unsigned short banks[74][256] = 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,2493, 295,2555, 295,2556,2495,2557,2558,2559,2496,2497,2560,2498,2561,2499,2562,2500, -2563,2564,2565,2527, 295, 295,2566, 295,2567, 295, 295, 295,2570,2571, 295,2572, +2563,2564,2565,2527, 295, 295,2566, 295, 295, 295, 295, 295,2570,2571, 295,2572, 2573, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, @@ -9897,7 +10267,7 @@ const unsigned short banks[74][256] = 232, 233, 234, 235,1583, 237, 238, 239,1584,1585, 240,2873, 242, 243, 244,2874, 246, 247,1588,1589, 249,2875,2876,2877,2878, 253, 254, 255,1591,1592,1593,2879, 1595, 259,1596,2880,1598,1599,1600,1601, 264, 265, 266,2881, 268, 108, 270,2859, -2882,2883, 273,1603,1604,1605, 276,2884,2885,2886,1609,1610,2887,1612,2888, 284, +2882,2883, 273,1603,1604,1605, 276,2884,2885,2886, 295,1610,2887,1612,2888, 284, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,2889,2889, 128, 129, 130,2890, 132,2891, 134, 135, 136, 137, 138, @@ -9934,14 +10304,14 @@ const unsigned short banks[74][256] = 2968,2969,2554,2970,2489,2971,2972,2973, 657, 575,2974,2975,2976, 779,2977,2978, 2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2553,2989,2990,2991,2992,2993, 2994,2995, 680, 796,2996, 797,2662,2997,2998,2999,2514,3000,3001,1913,3002,3003, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 384, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,3004, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,1219,1219, 308, 394, 395, 396, 397, 398, 399, 398, 400, 401, 402, 403, 404, 405, 406, 404, 406, 407, 404, 408, 404, 330, 409, 410, 411, 412, 413, 414, 415, 416,1220,1221, 419, 420, 341, 342, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 419, 430, 351, 431, 308, 432, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, + 428, 429, 419, 430, 351, 431, 308, 432, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { 2501,2502,2503,2504,2505,2506,2507, 730,2508,2509,2510,2511,2512,2513,2514,2515, @@ -9955,7 +10325,7 @@ const unsigned short banks[74][256] = 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,2493, 295,2555, 295,2556,2495,2557,2558,2559,2496,2497,2560,2498,2561,2499,2562,2500, -2563,3011,2565,2527, 295, 295,2566, 295,2567, 295, 295, 295,3012,3013,3014,3015, +2563,3011,2565,2527, 295, 295,2566, 295, 295, 295, 295, 295,3012,3013,3014,3015, 3016,3015,3016, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, @@ -10006,14 +10376,14 @@ const unsigned short banks[74][256] = 2059,2060,2061,2062,2063,2064,2065,2066,3089,2068,2069,2070,3090,3091,2072,2073, 2074,2075,2076,2077,2078,2079,2080, 275,2081,2082,1527,2083,2084,2085,2086,2087, 2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099, 122,2100,2101,2102, -2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103, -2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103, -2103,2103,2103,2104,2105,2106,2107,2108,2109,2110,2111,2110,2112,2113,2114,2113, -2115, 547,2115,2116,2103,2103,2117,2103,2118,2103,2103,2103,2119,2120,2121,2122, -2123,2124,2125,2126,2127, 160, 161, 162, 163,2128,2103,2129,2103,2103,2103,2103, -2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103, -2103,2103,2103,2103, 295,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103, -2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103,2103, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295,2104,2105,2106,2107,2108,2109,2110,2111,2110,2112,2113,2114,2113, +2115, 547,2115,2116, 295, 295,2117, 295,2118, 295, 295, 295,2119,2120,2121,2122, +2123,2124,2125,2126,2127, 160, 161, 162, 163,2128, 295,2129, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { 2501,2502,2503,2504,2505,2506,2507, 730,2508,2509,2510,2511,2512,2513,2514,2515, @@ -10027,75 +10397,75 @@ const unsigned short banks[74][256] = 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,2493, 295,2555, 295,3092,2495,2557,2558,2559,2496,2497,2562,2498,2561,2499,2562,2500, -2563,3011,2565,2527, 295, 295,2566, 295,2567, 295, 295, 295,2570,2571, 295,2572, +2563,3011,2565,2527, 295, 295,2566, 295, 295, 295, 295, 295,2570,2571, 295,2572, 3093, 295, 295, 295, 295, 295,3094, 295, 295,3095,3096, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,3097, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -1551,1552,1553,3101, 181, 182, 183,3102, 185,1556,1557,3103,1559, 188, 189,1560, -1561,1562, 193,1564,1565, 195, 196, 197, 198, 199, 200, 201, 202,1566,1567, 205, - 206, 207, 208,1568,1569,1570,1571, 211,1572,1573, 214, 215, 216, 217, 218, 219, - 220, 221,1574,1575,1576,1577,1578, 225,1579,1580,3100,1581,1582, 229, 230, 231, - 232, 233, 234, 235,1583, 237, 238, 239,1584,1585, 240,1586, 242, 243, 244,1587, - 246, 247,1588,1589, 249, 250, 251,1590, 252, 253, 254, 255,1591,1592,1593,1594, -1595, 259,1596,1597,1598,1599,1600,1601, 264, 265, 266, 267, 268, 269, 270, 271, -1602, 272, 273,1603,1604,1605, 276,1606,1607,1608,1609,1610,3104,3105, 283, 284, +3098,3205,3101,3129,3130,3131,3108,3132,3209,3210,3120,3133,3124,3134,3103,3135, +3136,3137,3113,3138,3139,3140,3141,3142,3143,3144,3145,3206,3121,3207,3208,3146, +3127,3147,3148,3211,3212,3149,3150,3151,3116,3106,3152,3110,3111,3213,3104,3126, +3105,3117,3153,3154,3102,3214,3155,3119,3215,3216,3115,3109,3217,3114,3112,3218, +3156,3219,3157,3158,3159,3107,3122,3128,3160,3222,3161,3162,3163,3164,3165,3166, +3167,3168,3169,3170,3171,3172,3173,3174,3223,3175,3176,3177,3118,3221,3220,3178, +3226,3241,3179,3180,3242,3181,3182,3183,3184,3185,3186,3187,3125,3188,3189,3190, +3191,3192,3193,3194,3123,3195,3196,3197,3198,3224,3199,3200,3201,3202,3203,3204, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 127,3107,3122,3126, 316,3123,3121,3124,3107,3125,3107,3127,3107, -3107, 329,3107,3108,3143,3109,3128,3129,3099,3144,1634,3110,3130,3131,3117,3119, -3136,3132,3133,3134,3137,3115,3138,3135,3098, 343, 344,3112,3113,3113,3142,3139, -3140,3141,3116,3106,3111,3114,3118,3120, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 127,3227,3244,3248,3268,3245,3243,3246,3227,3247,3227,3249,3227, +3227,3269,3227,3228,3270,3229,3250,3251,3100,3271,3258,3230,3252,3253,3237,3239, +3259,3254,3255,3256,3260,3235,3261,3257,3099,3265,3266,3232,3233,3233,3267,3262, +3263,3264,3236,3225,3231,3234,3238,3240, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -1551,1552,1553,3101, 181, 182, 183,3102, 185,1556,1557,3103,1559, 188, 189,1560, -1561,1562, 193,1564,1565, 195, 196, 197, 198, 199, 200, 201, 202,1566,1567, 205, - 206, 207, 208,1568,1569,1570,1571, 211,1572,1573, 214, 215, 216, 217, 218, 219, - 220, 221,1574,1575,1576,1577,1578, 225,1579,1580,3100,1581,1582, 229, 230, 231, - 232, 233, 234, 235,1583, 237, 238, 239,1584,1585, 240,1586, 242, 243, 244,1587, - 246, 247,1588,1589, 249, 250, 251,1590, 252, 253, 254, 255,1591,1592,1593,1594, -1595, 259,1596,1597,1598,1599,1600,1601, 264, 265, 266, 267, 268, 269, 270, 271, -1602, 272, 273,1603,1604,1605, 276,1606,1607,1608,1609,1610,3104,3105, 283, 284, +3098,3205,3101,3129,3130,3131,3108,3132,3209,3210,3120,3133,3124,3134,3103,3135, +3136,3137,3113,3138,3139,3140,3141,3142,3143,3144,3145,3206,3121,3207,3208,3146, +3127,3147,3148,3211,3212,3149,3150,3151,3116,3106,3152,3110,3111,3213,3104,3126, +3105,3117,3153,3154,3102,3214,3155,3119,3215,3216,3115,3109,3217,3114,3112,3218, +3156,3219,3157,3158,3159,3107,3122,3128,3160,3222,3161,3162,3163,3164,3165,3166, +3167,3168,3169,3170,3171,3172,3173,3174,3223,3175,3176,3177,3118,3221,3220,3178, +3226,3241,3179,3180,3242,3181,3182,3183,3184,3185,3186,3187,3125,3188,3189,3190, +3191,3192,3193,3194,3123,3195,3196,3197,3198,3224,3199,3200,3201,3202,3203,3204, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295,2430,2430,3149,3147,3148,3147,3145,3145,3145,3145,3145,3145,3145, -3145,3145,3145,3145,3145,3145,3150,3151,3173, 329,3152, 329,3153,3154,3155,3156, -3157,3158,3159,3160,3161, 349,3162,3163,3164,3165,3166,3148,3148,3148,3167,3168, -3169,3170, 349,3171,3172,3148,3155,3156,3146, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295,3274,3274,3277,3275,3276,3275,3272,3272,3272,3272,3272,3272,3272, +3272,3272,3272,3272,3272,3272,3278,3279,3301,3269,3280,3269,3281,3282,3283,3284, +3285,3286,3287,3288,3289, 349,3290,3291,3292,3293,3294,3276,3276,3276,3295,3296, +3297,3298, 349,3299,3300,3276,3283,3284,3273, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189, -3190,3191,3192,3193,3194,3195,3196,3196,3197,3198,3199,3200,3201,3202,3203,3204, -3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,3220, -3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3196,3232,3233,3234,3235, -3196,3236,3237,3238,3196,3239,3196,3240,3196,3241,3196,3242,3196,3243,3244,3245, -3246,3247,3248,3196,3249,3250,3196,3251,3252,3253,3254,3255,3196,3196,3256,3196, -3257,3196,3258,3196,3259,3260,3196,3261,3196,3196,3262,3196,3196,3196,3196,3196, -3196,3196,3196,3263,3196,3196,3196,3196,3196,3196,3264,3265,3196,3196,3196,3196, -3266,3267, 285,3268,3269, 287, 288,3270,3271,3271,3271,3271,3271,3271,3271,3271, -3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271, -3271,3271,3271,3272,3273,3271,3274,3271,3275,3276,3277,3278,3279,3280,3281,3282, -3282,3283,3280,3284,3271,3271,3285,3286,3271,3271,3271,3271,3271,3271,3271,3271, -3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271, -3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271, -3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271, -3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271,3271, +3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,3314,3315,3316,3317, +3318,3319,3320,3321,3322,3323,3324,3324,3325,3326,3327,3328,3329,3330,3331,3332, +3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,3344,3345,3346,3347,3348, +3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3324,3360,3361,3362,3363, +3324,3364,3365,3366,3324,3367,3324,3368,3324,3369,3324,3370,3324,3371,3372,3373, +3374,3375,3376,3324,3377,3378,3324,3379,3380,3381,3382,3383,3324,3324,3384,3324, +3385,3324,3386,3324,3387,3388,3324,3389,3324,3324,3390,3324,3324,3324,3324,3324, +3324,3324,3324,3391,3324,3324,3324,3324,3324,3324,3392,3393,3324,3324,3324,3324, +3394,3395, 285,3396,3397, 287, 288,3398,3399,3399,3399,3399,3399,3399,3399,3399, +3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399, +3399,3399,3399,3400,3401,3399,3402,3399,3403,3404,3405,3406,3407,3408,3409,3410, +3410,3411,3408,3412,3399,3399,3413,3414,3399,3399,3399,3399,3399,3399,3399,3399, +3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399, +3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399, +3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399, +3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399,3399, }, { -3287,3288, 466,3289, 713,3196,3290, 467,3291, 632,3292,3293,3294,3295,3296,3297, -3298, 598,3299,3300,3301,3302,3303,3304,1512,3305,3294,3306, 759, 437, 437,3307, -3308,3309, 439,3310, 440,3311, 442, 441,3312,3313,3314,3315,2306,3316,3317, 582, -3318,3319, 452,3320,3321,3290,3322,3323,3324, 778,3325,2312, 779,3326,3327,3328, -3329, 769,3330,3331,3332,3333, 663, 664,3334,2316,3335,3336,3337,1299,3338,3339, -3340,3341,3342,3343,3344,3345,3346, 442,3347,3348,3349,3304,3350,1669,3351,3352, -3353,3354,3355,3356,3353, 261,3357,3358,1919,2420,3359,3360, 676,3361,3362,3363, -3364,3365,3366,3367, 677,3368, 677,3369,3370, 677,3371, 455,3372,2421,3373, 465, +3415,3416, 466,3417, 713,3324,3418, 467,3419, 632,3420,3421,3422,3423,3424,3425, +3426, 598,3427,3428,3429,3430,3431,3432,1512,3433,3422,3434, 759, 437, 437,3435, +3436,3437, 439,3438, 440,3439, 442, 441,3440,3441,3442,3443,2306,3444,3445, 582, +3446,3447, 452,3448,3449,3418,3450,3451,3452, 778,3453,2312, 779,3454,3455,3456, +3457, 769,3458,3459,3460,3461, 663, 664,3462,2316,3463,3464,3465,1299,3466,3467, +3468,3469,3470,3471,3472,3473,3474, 442,3475,3476,3477,3432,3478,1669,3479,3480, +3481,3482,3483,3484,3481, 261,3485,3486,1919,2420,3487,3488, 676,3489,3490,3491, +3492,3493,3494,3495, 677,3496, 677,3497,3498, 677,3499, 455,3500,2421,3501, 465, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, @@ -10106,14 +10476,14 @@ const unsigned short banks[74][256] = 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -3374,3374,3375,3376,3377,3378,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387, -3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403, -3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,3419, -3420,3421,3422,3423,3424,3425,3426,3427,3425,3428,3429,3430,3431,3432,3433,3434, -3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3335,3447,3448,3449, -3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3462,3463,3464, -3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3479,3480, -3481,3482,3481,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495, +3502,3502,3503,3504,3505,3506,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515, +3516,3517,3518,3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531, +3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547, +3548,3549,3550,3551,3552,3553,3554,3555,3553,3556,3557,3558,3559,3560,3561,3562, +3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3463,3575,3576,3577, +3578,3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3590,3591,3592, +3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608, +3609,3610,3609,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, @@ -10135,155 +10505,155 @@ const unsigned short banks[74][256] = 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 127, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,3496, 150, 151, 152, 153, 154, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,3624, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -1551,1552,1553,1554, 181, 182, 183,1555, 185,1556,3497,3498,3499, 188, 189,1560, -1561,1562,1563,3500,1565, 195, 196, 197, 198, 199, 200, 201, 202,1566,1567, 205, - 206, 207, 208,1568,1569,1570,1571,3501,1572,1573, 214, 215, 216, 217, 218, 219, +1551,1552,1553,1554, 181, 182, 183,1555, 185,1556,3625,3626,3627, 188, 189,1560, +1561,1562,1563,3628,1565, 195, 196, 197, 198, 199, 200, 201, 202,1566,1567, 205, + 206, 207, 208,1568,1569,1570,1571,3629,1572,1573, 214, 215, 216, 217, 218, 219, 220, 221,1574,1575,1576,1577,1578, 225,1579,1580, 226,1581,1582, 229, 230, 231, 232, 233, 234, 235,1583, 237, 238, 239,1584,1585, 240,1586, 242, 243, 244,1587, 246, 247,1588,1589, 249, 250, 251,1590, 252, 253, 254, 255,1591,1592,1593,1594, 1595, 259,1596,1597,1598,1599,1600,1601, 264, 265, 266, 267, 268, 269, 270, 271, -1602, 272, 273,1603,1604,1605, 276,1606,1607,1608,1609,1610,3502,3503, 283, 284, +1602, 272, 273,1603,1604,1605, 276,1606,1607, 295, 295,1610,3630,3631, 295, 284, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 127,3504,1613,1614,3505,1616,3506,1618,3507,1620,3508,1622,3509, -3510,1625,3511,3512,1628,1629,1630,1631,3513,1633,1634,3514,1636,1637,1638,1639, + 295, 295, 295, 127,3632,1613,1614,3633,1616,3634,1618,3635,1620,3636,1622,3637, +3638,1625,3639,3640,1628,1629,1630,1631,3641,1633,1634,3642,1636,1637,1638,1639, 1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655, 1656,1657,1658,1659,1660,1661,1662,1663, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -3515,3516,3517,3518,3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530, -3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546, -3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562, -3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578, -3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594, -3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610, -3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626, -3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642, -3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643, -3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643, -3643,3643,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656, -3657,3658,3659,3660,3658,3661,3662,3658,3663,3658,3664,3665,3666,3667,3668,3669, -3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685, -3686,3687, 806, 806, 806, 806, 806,3643,3643,3643,3643,3643,3643,3643,3643,3643, -3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643, -3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643,3643, - }, - { -3287,1492,3688,3289, 713,3689,3690, 730,1914,3691,1533,3293,3692,3693,3694,3695, -3298,3696,3697,3698,3699,3700,3701,3702,3703,3704,3705,3706, 759, 437,3707,3708, -3308,3709,3710,3711,3712,3713, 442,3714,3715,3716,3717,3718,3719,3720,3721,3722, -3723,2306,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737, -3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753, -3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769, -3770,3771,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785, -3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,3371,3796,3797,2421,3798,3799, +3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658, +3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674, +3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685,3686,3687,3688,3689,3690, +3691,3692,3693,3694,3695,3696,3697,3698,3699,3700,3701,3702,3703,3704,3705,3706, +3707,3708,3709,3710,3711,3712,3713,3714,3715,3716,3717,3718,3719,3720,3721,3722, +3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738, +3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754, +3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656, -3657,3658,3659,3660,3658,3661,3662,3658,3663,3658,3664,3665,3666,3667,3668,3669, -3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685, -3686,3687, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784, +3785,3786,3787,3788,3786,3789,3790,3786,3791,3786,3792,3793,3794,3795,3796,3797, +3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813, +3814,3815, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815, -3816,3817,3818,3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831, -3832,3833,3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847, -3840,3848,3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862, -3863,3864,3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877, -3878,3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893, -3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909, -3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925, -3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926, -3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926, -3926,3926,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939, -3940,3941,3942,3660,3943,3944,3662,3945,3663,3946,3947,3665,3948,3949,3950,3951, -3952,3953,3954,3955,3956,3936,3676,3957,3958,3679,3959,3960,3961,3962,3684,3685, -3963,3964,3965,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926, -3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926, -3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926,3926, +3415,1492,3816,3417, 713,3817,3818, 730,1914,3819,1533,3421,3820,3821,3822,3823, +3426,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834, 759, 437,3835,3836, +3436,3837,3838,3839,3840,3841, 442,3842,3843,3844,3845,3846,3847,3848,3849,3850, +3851,2306,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865, +3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881, +3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897, +3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,3910,3911,3912,3913, +3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3499,3924,3925,2421,3926,3927, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784, +3785,3786,3787,3788,3786,3789,3790,3786,3791,3786,3792,3793,3794,3795,3796,3797, +3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813, +3814,3815, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815, -3816,3817,3818,3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3830,3966,3831, -3832,3833,3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3967,3845,3846,3847, -3840,3848,3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3968,3862, -3863,3864,3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877, -3969,3879,3970,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893, -3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3971,3972,3973,3907,3908,3909, -3910,3911,3912,3913,3974,3915,3916,3975,3918,3919,3920,3921,3922,3923,3924,3925, -3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976, -3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3977,3977,3977,3977,3978, -3977,3977,3977,3927,3928,3979,3930,3931,3932,3980,3934,3935,3936,3937,3938,3939, -3940,3941,3942,3660,3943,3944,3662,3945,3663,3946,3947,3665,3948,3949,3950,3951, -3952,3953,3954,3955,3956,3936,3676,3957,3958,3981,3982,3960,3983,3984,3684,3685, -3963,3964,3965,3977,3977,3977,3977,3977,3977,3976,3985,3985,3985,3985,3985,3985, -3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985, -3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985, +3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943, +3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,3959, +3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,3974,3975, +3968,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990, +3991,3992,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005, +4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021, +4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037, +4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067, +4068,4069,4070,3788,4071,4072,3790,4073,3791,4074,4075,3793,4076,4077,4078,4079, +4080,4081,4082,4083,4084,4064,3804,4085,4086,3807,4087,4088,4089,4090,3812,3813, +4091,4092,4093, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + }, + { +3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943, +3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3958,4094,3959, +3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,4095,3973,3974,3975, +3968,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,4096,3990, +3991,3992,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005, +4097,4007,4098,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021, +4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4099,4100,4101,4035,4036,4037, +4038,4039,4040,4041,4102,4043,4044,4103,4046,4047,4048,4049,4050,4051,4052,4053, +4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104, +4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4105,4105,4105,4105,4106, +4105,4105,4105,4055,4056,4107,4058,4059,4060,4108,4062,4063,4064,4065,4066,4067, +4068,4069,4070,3788,4071,4072,3790,4073,3791,4074,4075,3793,4076,4077,4078,4079, +4080,4081,4082,4083,4084,4064,3804,4085,4086,4109,4110,4088,4111,4112,3812,3813, +4091,4092,4093,4105,4105,4105,4105,4105,4105,4104,4113,4113,4113,4113,4113,4113, +4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113, +4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113, }, { 1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237, -1238,1239,1240,1241,1242,1243,1244,1245,3986,3987,3988,1249,1250,1376,1377,1253, -1378,1255,1256,3989,1380,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,3990, -1270,3991,3992,3993,3994,1275,1276,1277,1278,1279,1381,1281,1282,1283,1284,1285, +1238,1239,1240,1241,1242,1243,1244,1245,4114,4115,4116,1249,1250,1376,1377,1253, +1378,1255,1256,4117,1380,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,4118, +1270,4119,4120,4121,4122,1275,1276,1277,1278,1279,1381,1281,1282,1283,1284,1285, 1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301, -1302,1303,1304,1305,3995,1307,1308,1309,1309,1310,1311,1312,1313,1314,1315,1316, +1302,1303,1304,1305,4123,1307,1308,1309,1309,1310,1311,1312,1313,1314,1315,1316, 1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332, -1333,1334,1335,1336,1337,3996,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348, +1333,1334,1335,1336,1337,4124,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 312,1349,1350,3997,1352,3998,1354,3999,1355, 320,1356, 321,1357, + 295, 295, 295, 312,1349,1350,4125,1352,4126,1354,4127,1355, 320,1356, 321,1357, 1358,1359,1360,1361,1362,1363,1364,1383,1366,1359,1384,1361, 332, 333, 334, 335, - 336,1368,1369, 338, 339, 320,1370,1371,1371,1371,1371,1372,1373,1374,1375,1371, + 336,1368,1369, 338, 339, 320,1370, 295, 295, 295, 295,1372,1373,1374,1375, 295, 347, 348, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -4000,4001,4002,4003,4004,4005, 6, 7,4006, 9, 10,4007, 12, 13, 14, 15, -4008,4009,4010,4011, 20,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022, - 32,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036, 46, -4037,4038,4039,4040,4041,4042,4043, 54,4044,4045,4046,4047,4048,4049,4050,4051, -4052,4053,4054, 66,4055,4056, 69,4057,4058,4059,4060, 74, 75, 76, 77, 78, -4061,4062,4063, 82,4064,4065, 85,4066,4067, 88,4068,4069,4070,4071,4072,4073, - 95, 96, 97,4074,4075,4076,4077, 102, 103,4078, 105, 106, 107,4079,4080,4081, -4082, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,4083,4084,4085, 125,4086, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656, -3657,3658,3659,3660,3658,3661,3662,3658,3663,3658,3664,3665,3666,3667,3668,3669, -3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685, -3686,3687, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, +4128,4129,4130,4131,4132,4133, 6, 7,4134, 9, 10,4135, 12, 13, 14, 15, +4136,4137,4138,4139, 20,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150, + 32,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164, 46, +4165,4166,4167,4168,4169,4170,4171, 54,4172,4173,4174,4175,4176,4177,4178,4179, +4180,4181,4182, 66,4183,4184, 69,4185,4186,4187,4188, 74, 75, 76, 77, 78, +4189,4190,4191, 82,4192,4193, 85,4194,4195, 88,4196,4197,4198,4199,4200,4201, + 95, 96, 97,4202,4203,4204,4205, 102, 103,4206, 105, 106, 107,4207,4208,4209, +4210, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,4211,4212,4213, 125,4214, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784, +3785,3786,3787,3788,3786,3789,3790,3786,3791,3786,3792,3793,3794,3795,3796,3797, +3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813, +3814,3815, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -3287,3288, 466,3289, 713,3196,3290, 467,3291, 632,3292,3293,3294,3295,4087,3297, -3298, 598,4088,3300,3301,3302,3303,3304,4089,4090,4091,4092, 759, 437, 438,3307, -3308,3309, 439,3310, 440,4093, 442,4094,3312,3313,3314,3315,2306,4095,3317, 582, -3318,3319, 452,3320,3321,4096,3322,3323,3324, 778,3325,2312, 779,3326,3327,3328, -3329, 769,3330,3331,3332,3333, 663, 664,3334,2316,3335,3336,3337,1299,3338,3339, -3340,3341,4097,3343,3344,3345,4098, 442,3347,3348,3349,3304,3350,1669,3351,3352, -3353,3354,3355,3356,4099, 261,3357,3358,1919,2420,3359,3360, 676,3361,3362,3363, -3364,4100,3366,3367,4101,4102, 680,3369,3370, 462,3371, 455,3372,2421,3373, 465, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806,3644,3645,4103,3649,3648,4104,4105,4106,4107,4108,4109,4110,4111, -4112,3658,4113,3660,3658,3661,3662,3658,3663,3658,3664,2617,3666,3667,3668,3669, -3670,3671,3672,3673,3674, 160,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685, -3686,3687, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, +3415,3416, 466,3417, 713,3324,3418, 467,3419, 632,3420,3421,3422,3423,4215,3425, +3426, 598,4216,3428,3429,3430,3431,3432,4217,4218,4219,4220, 759, 437, 438,3435, +3436,3437, 439,3438, 440,4221, 442,4222,3440,3441,3442,3443,2306,4223,3445, 582, +3446,3447, 452,3448,3449,4224,3450,3451,3452, 778,3453,2312, 779,3454,3455,3456, +3457, 769,3458,3459,3460,3461, 663, 664,3462,2316,3463,3464,3465,1299,3466,3467, +3468,3469,4225,3471,3472,3473,4226, 442,3475,3476,3477,3432,3478,1669,3479,3480, +3481,3482,3483,3484,4227, 261,3485,3486,1919,2420,3487,3488, 676,3489,3490,3491, +3492,4228,3494,3495,4229,4230, 680,3497,3498, 462,3499, 455,3500,2421,3501, 465, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295,3772,3773,4231,3777,3776,4232,4233,4234,4235,4236,4237,4238,4239, +4240,3786,4241,3788,3786,3789,3790,3786,3791,3786,3792,2617,3794,3795,3796,3797, +3798,3799,3800,3801,3802, 160,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813, +3814,3815, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { 622, 179, 371, 180, 372, 373, 374, 375, 376, 377, 186, 378, 187, 379, 380, 190, @@ -10296,106 +10666,106 @@ const unsigned short banks[74][256] = 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127,4114,4115,4116, 141,4117,4118,4119,4118,4120,4118,4121,4122, -4123,1954,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137, -4138,4139,4140,4141,4142,4143, 163,4144, 625,4145,4146,4147,4148,4149,4150,4151, -4152,4153,4154,4155,4156,4157,4158, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127,4242,4243,4244, 141,4245,4246,4247,4246,4248,4246,4249,4250, +4251,1954,4252,4253,4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265, +4266,4267,4268,4269,4270,4271, 163,4272, 625,4273,4274,4275,4276,4277,4278,4279, +4280,4281,4282,4283,4284,4285,4286, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, }, { -4159,4160,1553,1554, 181,4161,4162,1555, 185,4163,3497,4164,1559, 188,4165,4166, -4167,1562,4168,4169,1565, 195,4170, 197,4171,4172, 200, 201, 28,1566,1567,4173, -4174,4175,4176,4177,4178,4179,4180,4181,1572,1573, 214, 215, 216, 217, 218, 219, - 220,4182,4183,1575,1576,1577,1578,4184,1579,1580,4185,1581,4186,4187,4188,4189, - 232, 233, 234, 235,4190, 237, 238,4191,1584,1585, 240,1586, 242, 243, 244,1587, - 246,4192,4193,1589, 249, 250, 251,1590, 252,4194, 254, 255,4195,4196,4197,4198, -1595,4199,1596,1597,1598,1599,1600,1601,4200,4201,4202, 267,4203,4204, 270,4205, -4206,4207, 273,1603,4208,1605, 276,4209,4210,4211,4212,1610,4213,4214,4215, 126, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806,4216,1470,1613,4217,1615,4218,1475,4219,1477,4220,1479,4221,1481, -1482,4222,1484,4223,4224,4225,1630,4226,2291,4227,1634,3514,1636,1637,1638,1639, -1640,4228,4229,1643,1644,1645,1646,4230, 342,4231,4232,1651,1652,1653,4233,4234, -1656,4235,1658,1659,1660,1661,1662,1663, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, +4287,4288,1553,1554, 181,4289,4290,1555, 185,4291,3625,4292,1559, 188,4293,4294, +4295,1562,4296,4297,1565, 195,4298, 197,4299,4300, 200, 201, 28,1566,1567,4301, +4302,4303,4304,4305,4306,4307,4308,4309,1572,1573, 214, 215, 216, 217, 218, 219, + 220,4310,4311,1575,1576,1577,1578,4312,1579,1580,4313,1581,4314,4315,4316,4317, + 232, 233, 234, 235,4318, 237, 238,4319,1584,1585, 240,1586, 242, 243, 244,1587, + 246,4320,4321,1589, 249, 250, 251,1590, 252,4322, 254, 255,4323,4324,4325,4326, +1595,4327,1596,1597,1598,1599,1600,1601,4328,4329,4330, 267,4331,4332, 270,4333, +4334,4335, 273,1603,4336,1605, 276,4337,4338,4339,4340,1610,4341,4342,4343, 126, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295,4344,1470,1613,4345,1615,4346,1475,4347,1477,4348,1479,4349,1481, +1482,4350,1484,4351,4352,4353,1630,4354,2291,4355,1634,3642,1636,1637,1638,1639, +1640,4356,4357,1643,1644,1645,1646,4358, 342,4359,4360,1651,1652,1653,4361,4362, +1656,4363,1658,1659,1660,1661,1662,1663, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -3643, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, + 295, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871,2216, 873, 874, 875, 876, 877, 878,2217, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894,2218, 896, 897, 898, 899, 900,2219,2220, 903,2221, 905,2222,2223, 2224, 909,2225, 911, 912,2226,2227, 915, 916,2228,2229, 919, 920, 921, 922, 923, -2230, 925, 926, 927, 928, 929,4236, 931, 932, 933, 934, 935,2232,2233, 938,2234, - 940,4237, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, - 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966,4238, 968,4239,3643,3643, -4240,4241,4242,4243,4244,4245,4246, 978,4247,4248,4249,4250,4251,4252,4253,4254, -4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265, 975, 971, 972, 973, 974, +2230, 925, 926, 927, 928, 929, 295, 931, 932, 933, 934, 935,2232,2233, 938,2234, + 940, 295, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, + 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966,4366, 968,4367, 295, 295, +4368,4369,4370,4371,4372,4373,4374, 978,4375,4376,4377,4378,4379,4380,4381,4382, +4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393, 975, 971, 972, 973, 974, 975, 310, 976, 977, 978, 974,2239, 980,2240, 982,2241, 984,2242, 985,2243, 987, 988,2244, 990, 325,2244, 325, 991,2244,2245,2246, 330, 993,2247,2248,2249, 997, 998,2250,2251,1001,1002,1003, 340,1004,1005,1006,1007,1008,1009, 310,1010,1011, -2252, 429,1003, 430,1013,1014, 974,1015,4266,4266,4266,4266,4266,4266,4266,4266, -4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266, -4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266,4266, +2252, 429,1003, 430,1013,1014, 974,1015, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -3287,4267,3196,3196,4268,3196,3196,3196,3196,3196,3196, 378,3196,3196,3694,3196, -3196,4269,3196,4270,4271,4272,3196,3196,3196, 370,3196,4273,4274,4275,4276,4277, -3196,4278,4279,4280,3310,3310,4281, 442,4282,3196,3196,4283,4284,4283, 676,4285, -4286,3196,3196,4287, 51,3196,3196,3196,4288,3324,4289,3196, 59,4290,4288, 62, -3196,4291,4291,4292, 67,3196, 664,4293,3196,2316,3196,4294, 70,3196,4295, 78, -4296,4297, 81,3196,3196,3196,3196,3196,3196,3196,3196, 90,3196,4298, 93,4299, -3196,3196,3196,3196,3196,3196,3196,4300,3196,3196,3196,3196,3196,3196,3196,3196, -3196,3196,3196,3196,3196,4101,3196,4301,3196,3196,3196,3196,3196,3196,3196,3196, -3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196, -3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196, -3196,3196,3196,4302,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313, -4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,3196,3196,4326, 154, -4327,4328,4329,3196,3196, 160,3196,3196,3196,4330,4331,4332,4333,4334,4335,3196, -3196,4336, 160,4337,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196, -3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196, -3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196,3196, +3415,4395,3324,3324,4396,3324,3324,3324,3324,3324,3324, 378,3324,3324,3822,3324, +3324,4397,3324,4398,4399,4400,3324,3324,3324, 370,3324,4401,4402,4403,4404,4405, +3324,4406,4407,4408,3438,3438,4409, 442,4410,3324,3324,4411,4412,4411, 676,4413, +4414,3324,3324,4415, 51,3324,3324,3324,4416,3452,4417,3324, 59,4418,4416, 62, +3324,4419,4419,4420, 67,3324, 664,4421,3324,2316,3324,4422, 70,3324,4423, 78, +4424,4425, 81,3324,3324,3324,3324,3324,3324,3324,3324, 90,3324,4426, 93,4427, +3324,3324,3324,3324,3324,3324,3324,4428,3324,3324,3324,3324,3324,3324,3324,3324, +3324,3324,3324,3324,3324,4229,3324,4429,3324,3324,3324,3324,3324,3324,3324,3324, +3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324, +3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324, +3324,3324,3324,4430,4430,4431,4432,4433,4434,4435,4436,4437,4438,4439,4440,4441, +4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,3324,3324,4454, 154, +4455,4456,4457,3324,3324, 160,3324,3324,3324,4458,4459,4460,4461,4462,4463,3324, +3324,4464, 160,4465,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324, +3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324, +3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324,3324, }, { -3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815, -3816,3817,3818,3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831, -3832,3833,3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847, -3840,3848,3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862, -3863,3864,3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877, -3878,3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893, -3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909, -3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,4338,3921,3922,3923,3924,3925, -3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976, -3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3976,3977,3977,3977,3977,3977, -3977,3977,3977,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939, -3940,3941,3942,3660,3943,3944,3662,3945,3663,3946,3947,3665,3948,3949,3950,3951, -3952,3953,3954,3955,3956,3936,3676,3957,3958,3679,3959,3960,3961,3962,3684,3685, -3963,3964,3965,3977,3977,3977,3977,3977,3977,3976,3985,3985,3985,3985,3985,3985, -3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985, -3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985,3985, +3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943, +3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,3959, +3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,3974,3975, +3968,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990, +3991,3992,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005, +4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021, +4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037, +4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4466,4049,4050,4051,4052,4053, +4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104, +4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4104,4105,4105,4105,4105,4105, +4105,4105,4105,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067, +4068,4069,4070,3788,4071,4072,3790,4073,3791,4074,4075,3793,4076,4077,4078,4079, +4080,4081,4082,4083,4084,4064,3804,4085,4086,3807,4087,4088,4089,4090,3812,3813, +4091,4092,4093,4105,4105,4105,4105,4105,4105,4104,4113,4113,4113,4113,4113,4113, +4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113, +4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113,4113, }, { -4339,4340,4341,4342,4343,4344,4345,4346,4347,4348,4349,4350,4351,4352,4353,4354, -4355,4356,4357,4358,4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370, -4371,4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386, -4387,4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402, -4403,4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418, -4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434, -4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450, -4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806,4467,4468,4469,4470,4471, -4472,4473,4474,4475,4476,4477,4217,4478,4218,4479,4480,4481,4482,4483,4221,4484, -4485,4222,4486,4487,4224,4488,4489,4226,4490,4227,4491,4492,4493,4494,4495,4496, -4497,4498,4499,4500,4501, 320,4502,4503,4504,4505,4506,4507,4508,1374,4509,4510, -4511,4512,4513,4514,4515,4516,4517,4518, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, +4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482, +4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498, +4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,4514, +4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,4529,4530, +4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,4544,4545,4546, +4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562, +4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,4574,4575,4576,4577,4578, +4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,4595,4596,4597,4598,4599, +4600,4601,4602,4603,4604,4605,4606,4607,4346,4608,4609,4610,4611,4612,4349,4613, +4614,4615,4616,4617,4352,4618,4619,4354,4620,4621,4622,4623,4624,4625,4626,4627, +4628,4629,4630,4631,4632, 320,4633,4634,4635,4636,4637,4638,4639,1374,4640,4641, +4642,4643,4644,4645,4646,4647,4648,4649, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, { -4519,4520,4521,4522,4520,4523,4524,4525,4526,4527,4528,4530,4531,4532,4533,4534, -4535,4537,4539,4532,4541,4542,4543,4544,4545,4546,4547, 295, 28, 29, 30, 31, +4650,4651,4652,4653,4651,4654,4655,4656,4657,4658,4659,4661,4662,4663,4664,4665, +4666,4668,4670,4663,4672,4673,4674,4675,4676,4677,4678, 295, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 33, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, @@ -10404,16 +10774,34 @@ const unsigned short banks[74][256] = 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 127,4536, 128,4538, 130, 131, 132,4540, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144,4529, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 295, 295, 295, 127,4667, 128,4669, 130, 131, 132,4671, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144,4660, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + }, + { +4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,4690,4691,4692,3423,4689,4693, +3426,4694,4695,3426,4696,4697,4697,4697, 868, 869, 870,4698,4699,4700,4701,4702, +4703,4704,4705,4705,4706,4703,4707,4708,3970,4709,4710,4710,4711,4712,4713,4714, +4715,4716,4717,4717,4718,4224,3450,4719,4720,4721,4722,4723,4724,4720,4720,4725, +3457, 769,3458,3459,4726,4727,4728,4729,4730,4731,4732,4733,4734,4731,1300,4735, +4736,4737,4731,4696,4738,4720,4739,4740,3475,4741,4742,4743,4744,1314,4745,4746, +4747,4748,4749,4742,4742,1322,4750,4751,4752,4753,4754,4753,3423,4755,3970,4756, +4757,1334,4757,4758,4759,4760, 792,4761,1341,1342,1343,1344,4762,4763,4764,1348, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295,4765,4765,4766,4767,4766,4768,4769,4770,4771,4772,4773,4774,4775, +4776,4777,4778,4779,4780,4781,4782,4783,4784,4777,4785,4786,4787,4788,4789,4790, +4791,4792,4793,4794,4795,4796,4797,4794,4795,4796,4798,4799,4800,4801,1375, 295, +4802,4803, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, }, }; -const AdlBankSetup adlbanksetup[74] = +const AdlBankSetup adlbanksetup[75] = { {0, 1, 1, 0, 0}, //Bank 0, AIL (Star Control 3, Albion, Empire 2, etc.) {0, 1, 1, 0, 0}, //Bank 1, Bisqwit (selection of 4op and 2op) @@ -10482,11 +10870,12 @@ const AdlBankSetup adlbanksetup[74] = {2, 0, 0, 0, 0}, //Bank 64, DMX (Raptor) {3, 0, 0, 0, 0}, //Bank 65, OP3 (Modded GMOPL by Wohlstand) {3, 0, 0, 0, 0}, //Bank 66, SB (Jammey O'Connel's bank) - {3, 0, 0, 0, 0}, //Bank 67, TMB (Default bank of Build Engine) + {3, 0, 0, 0, 0}, //Bank 67, TMB (Default bank of Apgee Sound System) {0, 1, 1, 0, 0}, //Bank 68, WOPL (4op bank by James Alan Nguyen and Wohlstand) {3, 0, 0, 0, 0}, //Bank 69, TMB (Blood) {3, 0, 0, 0, 0}, //Bank 70, TMB (Lee) {3, 0, 0, 0, 0}, //Bank 71, TMB (Nam) - {1, 0, 0, 0, 0}, //Bank 72, WOPL (DMXOPL3 bank by Sneakernets) - {1, 0, 0, 0, 0} //Bank 73, EA (Cartooners) + {0, 0, 0, 0, 0}, //Bank 72, WOPL (DMXOPL3 bank by Sneakernets) + {1, 0, 0, 0, 0}, //Bank 73, EA (Cartooners) + {0, 0, 1, 0, 0} //Bank 74, WOPL (Apogee IMF 90-ish) }; diff --git a/src/sound/adlmidi/adldata.hh b/src/sound/adlmidi/adldata.hh index e9ff00b25..104db82cd 100644 --- a/src/sound/adlmidi/adldata.hh +++ b/src/sound/adlmidi/adldata.hh @@ -24,8 +24,16 @@ #ifndef ADLDATA_H #define ADLDATA_H +#include #include +#pragma pack(push, 1) +#define ADLDATA_BYTE_COMPARABLE(T) \ + inline bool operator==(const T &a, const T &b) \ + { return !memcmp(&a, &b, sizeof(T)); } \ + inline bool operator!=(const T &a, const T &b) \ + { return !operator==(a, b); } + extern const struct adldata { uint32_t modulator_E862, carrier_E862; // See below @@ -34,22 +42,46 @@ extern const struct adldata int8_t finetune; } adl[]; +ADLDATA_BYTE_COMPARABLE(struct adldata) +enum { adlDefaultNumber = 189 }; extern const struct adlinsdata { - enum { Flag_Pseudo4op = 0x01, Flag_NoSound = 0x02 }; + enum { Flag_Pseudo4op = 0x01, Flag_NoSound = 0x02, Flag_Real4op = 0x04 }; uint16_t adlno1, adlno2; uint8_t tone; uint8_t flags; uint16_t ms_sound_kon; // Number of milliseconds it produces sound; uint16_t ms_sound_koff; - double voice2_fine_tune; + double voice2_fine_tune; } adlins[]; +ADLDATA_BYTE_COMPARABLE(struct adlinsdata) int maxAdlBanks(); extern const unsigned short banks[][256]; extern const char* const banknames[]; +enum { adlNoteOnMaxTime = 40000 }; + +/** + * @brief Instrument data with operators included + */ +struct adlinsdata2 +{ + adldata adl[2]; + uint8_t tone; + uint8_t flags; + uint16_t ms_sound_kon; // Number of milliseconds it produces sound; + uint16_t ms_sound_koff; + double voice2_fine_tune; + adlinsdata2() {} + explicit adlinsdata2(const adlinsdata &d); +}; +ADLDATA_BYTE_COMPARABLE(struct adlinsdata2) + +#undef ADLDATA_BYTE_COMPARABLE +#pragma pack(pop) + /** * @brief Bank global setup */ @@ -62,4 +94,26 @@ extern const struct AdlBankSetup bool scaleModulators; } adlbanksetup[]; +/** + * @brief Conversion of storage formats + */ +inline adlinsdata2::adlinsdata2(const adlinsdata &d) + : tone(d.tone), flags(d.flags), + ms_sound_kon(d.ms_sound_kon), ms_sound_koff(d.ms_sound_koff), + voice2_fine_tune(d.voice2_fine_tune) +{ + adl[0] = ::adl[d.adlno1]; + adl[1] = ::adl[d.adlno2]; +} + +/** + * @brief Convert external instrument to internal instrument + */ +void cvt_ADLI_to_FMIns(adlinsdata2 &dst, const struct ADL_Instrument &src); + +/** + * @brief Convert internal instrument to external instrument + */ +void cvt_FMIns_to_ADLI(struct ADL_Instrument &dst, const adlinsdata2 &src); + #endif //ADLDATA_H diff --git a/src/sound/adlmidi/adlmidi.cpp b/src/sound/adlmidi/adlmidi.cpp index db97447a2..9210b5be3 100644 --- a/src/sound/adlmidi/adlmidi.cpp +++ b/src/sound/adlmidi/adlmidi.cpp @@ -37,6 +37,13 @@ static ADL_Version adl_version = { ADLMIDI_VERSION_PATCHLEVEL }; +static const ADLMIDI_AudioFormat adl_DefaultAudioFormat = +{ + ADLMIDI_SampleType_S16, + sizeof(int16_t), + 2 * sizeof(int16_t), +}; + /*---------------------------EXPORTS---------------------------*/ ADLMIDI_EXPORT struct ADL_MIDIPlayer *adl_init(long sample_rate) @@ -67,7 +74,12 @@ ADLMIDI_EXPORT int adl_setNumChips(ADL_MIDIPlayer *device, int numCards) return -2; MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); +#ifdef ADLMIDI_HW_OPL + (void)numCards; + play->m_setup.NumCards = 1; +#else play->m_setup.NumCards = static_cast(numCards); +#endif if(play->m_setup.NumCards < 1 || play->m_setup.NumCards > MaxCards) { play->setErrorString("number of chips may only be 1.." MaxCards_STR ".\n"); @@ -108,7 +120,7 @@ ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank) if(static_cast(bankno) >= NumBanks) { char errBuf[150]; - snprintf(errBuf, 150, "Embedded bank number may only be 0..%u!\n", (NumBanks - 1)); + snprintf(errBuf, 150, "Embedded bank number may only be 0..%u!\n", static_cast(NumBanks - 1)); play->setErrorString(errBuf); return -1; } @@ -131,6 +143,142 @@ ADLMIDI_EXPORT const char *const *adl_getBankNames() return banknames; } +ADLMIDI_EXPORT int adl_reserveBanks(ADL_MIDIPlayer *device, unsigned banks) +{ + if(!device) + return -1; + MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); + OPL3::BankMap &map = play->opl.dynamic_banks; + map.reserve(banks); + return (int)map.capacity(); +} + +ADLMIDI_EXPORT int adl_getBank(ADL_MIDIPlayer *device, const ADL_BankId *idp, int flags, ADL_Bank *bank) +{ + if(!device || !idp || !bank) + return -1; + + ADL_BankId id = *idp; + if(id.lsb > 127 || id.msb > 127 || id.percussive > 1) + return -1; + unsigned idnumber = (id.msb << 8) | id.lsb | (id.percussive ? OPL3::PercussionTag : 0); + + MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); + OPL3::BankMap &map = play->opl.dynamic_banks; + + OPL3::BankMap::iterator it; + if(!(flags & ADLMIDI_Bank_Create)) + { + it = map.find(idnumber); + if(it == map.end()) + return -1; + } + else + { + std::pair value; + value.first = idnumber; + memset(&value.second, 0, sizeof(value.second)); + for (unsigned i = 0; i < 128; ++i) + value.second.ins[i].flags = adlinsdata::Flag_NoSound; + + std::pair ir; + if(flags & ADLMIDI_Bank_CreateRt) + { + ir = map.insert(value, OPL3::BankMap::do_not_expand_t()); + if(ir.first == map.end()) + return -1; + } + else + ir = map.insert(value); + it = ir.first; + } + + it.to_ptrs(bank->pointer); + return 0; +} + +ADLMIDI_EXPORT int adl_getBankId(ADL_MIDIPlayer *device, const ADL_Bank *bank, ADL_BankId *id) +{ + if(!device || !bank) + return -1; + + OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer); + unsigned idnumber = it->first; + id->msb = (idnumber >> 8) & 127; + id->lsb = idnumber & 127; + id->percussive = (idnumber & OPL3::PercussionTag) ? 1 : 0; + return 0; +} + +ADLMIDI_EXPORT int adl_removeBank(ADL_MIDIPlayer *device, ADL_Bank *bank) +{ + if(!device || !bank) + return -1; + + MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); + OPL3::BankMap &map = play->opl.dynamic_banks; + OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer); + size_t size = map.size(); + map.erase(it); + return (map.size() != size) ? 0 : -1; +} + +ADLMIDI_EXPORT int adl_getFirstBank(ADL_MIDIPlayer *device, ADL_Bank *bank) +{ + if(!device) + return -1; + + MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); + OPL3::BankMap &map = play->opl.dynamic_banks; + + OPL3::BankMap::iterator it = map.begin(); + if(it == map.end()) + return -1; + + it.to_ptrs(bank->pointer); + return 0; +} + +ADLMIDI_EXPORT int adl_getNextBank(ADL_MIDIPlayer *device, ADL_Bank *bank) +{ + if(!device) + return -1; + + MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); + OPL3::BankMap &map = play->opl.dynamic_banks; + + OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer); + if(++it == map.end()) + return -1; + + it.to_ptrs(bank->pointer); + return 0; +} + +ADLMIDI_EXPORT int adl_getInstrument(ADL_MIDIPlayer *device, const ADL_Bank *bank, unsigned index, ADL_Instrument *ins) +{ + if(!device || !bank || index > 127 || !ins) + return 1; + + OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer); + cvt_FMIns_to_ADLI(*ins, it->second.ins[index]); + ins->version = 0; + return 0; +} + +ADLMIDI_EXPORT int adl_setInstrument(ADL_MIDIPlayer *device, ADL_Bank *bank, unsigned index, const ADL_Instrument *ins) +{ + if(!device || !bank || index > 127 || !ins) + return 1; + + if(ins->version != 0) + return 1; + + OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer); + cvt_ADLI_to_FMIns(it->second.ins[index], *ins); + return 0; +} + ADLMIDI_EXPORT int adl_setNumFourOpsChn(ADL_MIDIPlayer *device, int ops4) { if(!device) @@ -165,7 +313,9 @@ ADLMIDI_EXPORT void adl_setPercMode(ADL_MIDIPlayer *device, int percmod) if(!device) return; MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); play->m_setup.AdlPercussionMode = percmod; - play->opl.AdlPercussionMode = play->m_setup.AdlPercussionMode; + play->opl.AdlPercussionMode = play->m_setup.AdlPercussionMode < 0 ? + play->opl.dynamic_bank_setup.adLibPercussions : + (play->m_setup.AdlPercussionMode != 0); play->opl.updateFlags(); } @@ -174,7 +324,9 @@ ADLMIDI_EXPORT void adl_setHVibrato(ADL_MIDIPlayer *device, int hvibro) if(!device) return; MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); play->m_setup.HighVibratoMode = hvibro; - play->opl.HighVibratoMode = play->m_setup.HighVibratoMode; + play->opl.HighVibratoMode = play->m_setup.HighVibratoMode < 0 ? + play->opl.dynamic_bank_setup.deepVibrato : + (play->m_setup.HighVibratoMode != 0); play->opl.updateDeepFlags(); } @@ -183,7 +335,9 @@ ADLMIDI_EXPORT void adl_setHTremolo(ADL_MIDIPlayer *device, int htremo) if(!device) return; MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); play->m_setup.HighTremoloMode = htremo; - play->opl.HighTremoloMode = play->m_setup.HighTremoloMode; + play->opl.HighTremoloMode = play->m_setup.HighTremoloMode < 0 ? + play->opl.dynamic_bank_setup.deepTremolo : + (play->m_setup.HighTremoloMode != 0); play->opl.updateDeepFlags(); } @@ -192,7 +346,16 @@ ADLMIDI_EXPORT void adl_setScaleModulators(ADL_MIDIPlayer *device, int smod) if(!device) return; MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); play->m_setup.ScaleModulators = smod; - play->opl.ScaleModulators = play->m_setup.ScaleModulators; + play->opl.ScaleModulators = play->m_setup.ScaleModulators < 0 ? + play->opl.dynamic_bank_setup.scaleModulators : + (play->m_setup.ScaleModulators != 0); +} + +ADLMIDI_EXPORT void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *device, int fr_brightness) +{ + if(!device) return; + MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); + play->m_setup.fullRangeBrightnessCC74 = (fr_brightness != 0); } ADLMIDI_EXPORT void adl_setLoopEnabled(ADL_MIDIPlayer *device, int loopEn) @@ -202,12 +365,16 @@ ADLMIDI_EXPORT void adl_setLoopEnabled(ADL_MIDIPlayer *device, int loopEn) play->m_setup.loopingIsEnabled = (loopEn != 0); } +/* !!!DEPRECATED!!! */ ADLMIDI_EXPORT void adl_setLogarithmicVolumes(struct ADL_MIDIPlayer *device, int logvol) { if(!device) return; MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); - play->m_setup.LogarithmicVolumes = logvol; - play->opl.LogarithmicVolumes = play->m_setup.LogarithmicVolumes; + play->m_setup.LogarithmicVolumes = (logvol != 0); + if(play->m_setup.LogarithmicVolumes) + play->opl.ChangeVolumeRangesModel(ADLMIDI_VolumeModel_NativeOPL3); + else + play->opl.ChangeVolumeRangesModel(static_cast(play->opl.m_volumeScale)); } ADLMIDI_EXPORT void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *device, int volumeModel) @@ -215,7 +382,10 @@ ADLMIDI_EXPORT void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *device, int v if(!device) return; MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); play->m_setup.VolumeModel = volumeModel; - play->opl.ChangeVolumeRangesModel(static_cast(volumeModel)); + if(play->m_setup.VolumeModel == ADLMIDI_VolumeModel_AUTO)//Use bank default volume model + play->opl.m_volumeScale = (OPL3::VolumesScale)play->opl.dynamic_bank_setup.volumeModel; + else + play->opl.ChangeVolumeRangesModel(static_cast(volumeModel)); } ADLMIDI_EXPORT int adl_openBankFile(struct ADL_MIDIPlayer *device, const char *filePath) @@ -312,16 +482,64 @@ ADLMIDI_EXPORT int adl_openData(ADL_MIDIPlayer *device, const void *mem, unsigne ADLMIDI_EXPORT const char *adl_emulatorName() { - #ifdef ADLMIDI_USE_DOSBOX_OPL - return "DosBox"; - #else - return "Nuked"; - #endif + return ""; } +ADLMIDI_EXPORT const char *adl_chipEmulatorName(struct ADL_MIDIPlayer *device) +{ + if(device) + { + #ifndef ADLMIDI_HW_OPL + MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); + if(play && !play->opl.cardsOP2.empty()) + return play->opl.cardsOP2[0]->emulatorName(); + #else + return "Hardware OPL3 chip on 0x330"; + #endif + } + return "Unknown"; +} + +ADLMIDI_EXPORT int adl_switchEmulator(struct ADL_MIDIPlayer *device, int emulator) +{ + if(device) + { + MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); + if(play && (emulator >= 0) && (emulator < ADLMIDI_EMU_end)) + { + play->m_setup.emulator = emulator; + adl_reset(device); + return 0; + } + play->setErrorString("OPL3 MIDI: Unknown emulation core!"); + } + return -1; +} + + +ADLMIDI_EXPORT int adl_setRunAtPcmRate(ADL_MIDIPlayer *device, int enabled) +{ + if(device) + { + MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); + if(play) + { + play->m_setup.runAtPcmRate = (enabled != 0); + adl_reset(device); + return 0; + } + } + return -1; +} + + ADLMIDI_EXPORT const char *adl_linkedLibraryVersion() { +#if !defined(ADLMIDI_ENABLE_HQ_RESAMPLER) return ADLMIDI_VERSION; +#else + return ADLMIDI_VERSION " (HQ)"; +#endif } ADLMIDI_EXPORT const ADL_Version *adl_linkedVersion() @@ -373,9 +591,10 @@ ADLMIDI_EXPORT void adl_reset(struct ADL_MIDIPlayer *device) return; MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); play->m_setup.tick_skip_samples_delay = 0; - play->opl.Reset(play->m_setup.PCM_RATE); + play->opl.runAtPcmRate = play->m_setup.runAtPcmRate; + play->opl.Reset(play->m_setup.emulator, play->m_setup.PCM_RATE, play); play->ch.clear(); - play->ch.resize(play->opl.NumChannels); + play->ch.resize((size_t)play->opl.NumChannels); } ADLMIDI_EXPORT double adl_totalTimeLength(struct ADL_MIDIPlayer *device) @@ -568,31 +787,156 @@ ADLMIDI_EXPORT void adl_setDebugMessageHook(struct ADL_MIDIPlayer *device, ADL_D play->hooks.onDebugMessage_userData = userData; } - - -inline static void SendStereoAudio(int &samples_requested, - ssize_t &in_size, - short *_in, - ssize_t out_pos, - short *_out) +#ifndef ADLMIDI_HW_OPL +template +static void CopySamplesRaw(ADL_UInt8 *dstLeft, ADL_UInt8 *dstRight, const int32_t *src, + size_t frameCount, unsigned sampleOffset) { - if(!in_size) - return; - size_t offset = static_cast(out_pos); - size_t inSamples = static_cast(in_size * 2); - size_t maxSamples = static_cast(samples_requested) - offset; - size_t toCopy = std::min(maxSamples, inSamples); - std::memcpy(_out + out_pos, _in, toCopy * sizeof(short)); + for(size_t i = 0; i < frameCount; ++i) { + *(Dst *)(dstLeft + (i * sampleOffset)) = src[2 * i]; + *(Dst *)(dstRight + (i * sampleOffset)) = src[(2 * i) + 1]; + } } +template +static void CopySamplesTransformed(ADL_UInt8 *dstLeft, ADL_UInt8 *dstRight, const int32_t *src, + size_t frameCount, unsigned sampleOffset, + Ret(&transform)(int32_t)) +{ + for(size_t i = 0; i < frameCount; ++i) { + *(Dst *)(dstLeft + (i * sampleOffset)) = (Dst)transform(src[2 * i]); + *(Dst *)(dstRight + (i * sampleOffset)) = (Dst)transform(src[(2 * i) + 1]); + } +} -ADLMIDI_EXPORT int adl_play(ADL_MIDIPlayer *device, int sampleCount, short *out) +static int SendStereoAudio(int samples_requested, + ssize_t in_size, + int32_t *_in, + ssize_t out_pos, + ADL_UInt8 *left, + ADL_UInt8 *right, + const ADLMIDI_AudioFormat *format) +{ + if(!in_size) + return 0; + size_t outputOffset = static_cast(out_pos); + size_t inSamples = static_cast(in_size * 2); + size_t maxSamples = static_cast(samples_requested) - outputOffset; + size_t toCopy = std::min(maxSamples, inSamples); + + ADLMIDI_SampleType sampleType = format->type; + const unsigned containerSize = format->containerSize; + const unsigned sampleOffset = format->sampleOffset; + + left += (outputOffset / 2) * sampleOffset; + right += (outputOffset / 2) * sampleOffset; + + typedef int32_t(&pfnConvert)(int32_t); + typedef float(&ffnConvert)(int32_t); + typedef double(&dfnConvert)(int32_t); + + switch(sampleType) { + case ADLMIDI_SampleType_S8: + case ADLMIDI_SampleType_U8: + { + pfnConvert cvt = (sampleType == ADLMIDI_SampleType_S8) ? adl_cvtS8 : adl_cvtU8; + switch(containerSize) { + case sizeof(int8_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + case sizeof(int16_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + case sizeof(int32_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + default: + return -1; + } + break; + } + case ADLMIDI_SampleType_S16: + case ADLMIDI_SampleType_U16: + { + pfnConvert cvt = (sampleType == ADLMIDI_SampleType_S16) ? adl_cvtS16 : adl_cvtU16; + switch(containerSize) { + case sizeof(int16_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + case sizeof(int32_t): + CopySamplesRaw(left, right, _in, toCopy / 2, sampleOffset); + break; + default: + return -1; + } + break; + } + case ADLMIDI_SampleType_S24: + case ADLMIDI_SampleType_U24: + { + pfnConvert cvt = (sampleType == ADLMIDI_SampleType_S24) ? adl_cvtS24 : adl_cvtU24; + switch(containerSize) { + case sizeof(int32_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + default: + return -1; + } + break; + } + case ADLMIDI_SampleType_S32: + case ADLMIDI_SampleType_U32: + { + pfnConvert cvt = (sampleType == ADLMIDI_SampleType_S32) ? adl_cvtS32 : adl_cvtU32; + switch(containerSize) { + case sizeof(int32_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + default: + return -1; + } + break; + } + case ADLMIDI_SampleType_F32: + { + if(containerSize != sizeof(float)) + return -1; + ffnConvert cvt = adl_cvtReal; + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + } + case ADLMIDI_SampleType_F64: + { + if(containerSize != sizeof(double)) + return -1; + dfnConvert cvt = adl_cvtReal; + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + } + default: + return -1; + } + + return 0; +} +#endif + +ADLMIDI_EXPORT int adl_play(struct ADL_MIDIPlayer *device, int sampleCount, short *out) +{ + return adl_playFormat(device, sampleCount, (ADL_UInt8 *)out, (ADL_UInt8 *)(out + 1), &adl_DefaultAudioFormat); +} + +ADLMIDI_EXPORT int adl_playFormat(ADL_MIDIPlayer *device, int sampleCount, + ADL_UInt8 *out_left, ADL_UInt8 *out_right, + const ADLMIDI_AudioFormat *format) { #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER #ifdef ADLMIDI_HW_OPL (void)device; (void)sampleCount; - (void)out; + (void)out_left; + (void)out_right; + (void)format; return 0; #else sampleCount -= sampleCount % 2; //Avoid even sample requests @@ -646,33 +990,23 @@ ADLMIDI_EXPORT int adl_play(ADL_MIDIPlayer *device, int sampleCount, short *out) ssize_t in_generatedPhys = in_generatedStereo * 2; //! Unsigned total sample count //fill buffer with zeros - int16_t *out_buf = player->outBuf; - std::memset(out_buf, 0, static_cast(in_generatedPhys) * sizeof(int16_t)); + int32_t *out_buf = player->outBuf; + std::memset(out_buf, 0, static_cast(in_generatedPhys) * sizeof(out_buf[0])); unsigned int chips = player->opl.NumCards; if(chips == 1) { - #ifdef ADLMIDI_USE_DOSBOX_OPL - player->opl.cards[0].GenerateArr(out_buf, &in_generatedStereo); - in_generatedPhys = in_generatedStereo * 2; - #else - OPL3_GenerateStream(&player->opl.cards[0], out_buf, static_cast(in_generatedStereo)); - #endif + player->opl.cardsOP2[0]->generate32(out_buf, (size_t)in_generatedStereo); } else if(n_periodCountStereo > 0) { /* Generate data from every chip and mix result */ - for(unsigned card = 0; card < chips; ++card) - { - #ifdef ADLMIDI_USE_DOSBOX_OPL - player->opl.cards[card].GenerateArrMix(out_buf, &in_generatedStereo); - in_generatedPhys = in_generatedStereo * 2; - #else - OPL3_GenerateStreamMix(&player->opl.cards[card], out_buf, static_cast(in_generatedStereo)); - #endif - } + for(size_t card = 0; card < chips; ++card) + player->opl.cardsOP2[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo); } + /* Process it */ - SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out); + if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1) + return 0; left -= (int)in_generatedPhys; gotten_len += (in_generatedPhys) /* - setup.stored_samples*/; @@ -698,11 +1032,20 @@ ADLMIDI_EXPORT int adl_play(ADL_MIDIPlayer *device, int sampleCount, short *out) ADLMIDI_EXPORT int adl_generate(struct ADL_MIDIPlayer *device, int sampleCount, short *out) +{ + return adl_generateFormat(device, sampleCount, (ADL_UInt8 *)out, (ADL_UInt8 *)(out + 1), &adl_DefaultAudioFormat); +} + +ADLMIDI_EXPORT int adl_generateFormat(struct ADL_MIDIPlayer *device, int sampleCount, + ADL_UInt8 *out_left, ADL_UInt8 *out_right, + const ADLMIDI_AudioFormat *format) { #ifdef ADLMIDI_HW_OPL (void)device; (void)sampleCount; - (void)out; + (void)out_left; + (void)out_right; + (void)format; return 0; #else sampleCount -= sampleCount % 2; //Avoid even sample requests @@ -739,33 +1082,20 @@ ADLMIDI_EXPORT int adl_generate(struct ADL_MIDIPlayer *device, int sampleCount, ssize_t in_generatedPhys = in_generatedStereo * 2; //! Unsigned total sample count //fill buffer with zeros - int16_t *out_buf = player->outBuf; - std::memset(out_buf, 0, static_cast(in_generatedPhys) * sizeof(int16_t)); + int32_t *out_buf = player->outBuf; + std::memset(out_buf, 0, static_cast(in_generatedPhys) * sizeof(out_buf[0])); unsigned int chips = player->opl.NumCards; if(chips == 1) - { - #ifdef ADLMIDI_USE_DOSBOX_OPL - player->opl.cards[0].GenerateArr(out_buf, &in_generatedStereo); - in_generatedPhys = in_generatedStereo * 2; - #else - OPL3_GenerateStream(&player->opl.cards[0], out_buf, static_cast(in_generatedStereo)); - #endif - } + player->opl.cardsOP2[0]->generate32(out_buf, (size_t)in_generatedStereo); else if(n_periodCountStereo > 0) { /* Generate data from every chip and mix result */ for(unsigned card = 0; card < chips; ++card) - { - #ifdef ADLMIDI_USE_DOSBOX_OPL - player->opl.cards[card].GenerateArrMix(out_buf, &in_generatedStereo); - in_generatedPhys = in_generatedStereo * 2; - #else - OPL3_GenerateStreamMix(&player->opl.cards[card], out_buf, static_cast(in_generatedStereo)); - #endif - } + player->opl.cardsOP2[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo); } /* Process it */ - SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out); + if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1) + return 0; left -= (int)in_generatedPhys; gotten_len += (in_generatedPhys) /* - setup.stored_samples*/; diff --git a/src/sound/adlmidi/adlmidi.h b/src/sound/adlmidi/adlmidi.h index 10fe4ddff..51cd968d0 100644 --- a/src/sound/adlmidi/adlmidi.h +++ b/src/sound/adlmidi/adlmidi.h @@ -30,13 +30,14 @@ extern "C" { #define ADLMIDI_VERSION_MAJOR 1 #define ADLMIDI_VERSION_MINOR 3 -#define ADLMIDI_VERSION_PATCHLEVEL 2 +#define ADLMIDI_VERSION_PATCHLEVEL 3 -#define ADLMIDI_TOSTR(s) #s +#define ADLMIDI_TOSTR_I(s) #s +#define ADLMIDI_TOSTR(s) ADLMIDI_TOSTR_I(s) #define ADLMIDI_VERSION \ - ADLMIDI_TOSTR(OPNMIDI_VERSION_MAJOR) "." \ - ADLMIDI_TOSTR(OPNMIDI_VERSION_MINOR) "." \ - ADLMIDI_TOSTR(OPNMIDI_VERSION_PATCHLEVEL) + ADLMIDI_TOSTR(ADLMIDI_VERSION_MAJOR) "." \ + ADLMIDI_TOSTR(ADLMIDI_VERSION_MINOR) "." \ + ADLMIDI_TOSTR(ADLMIDI_VERSION_PATCHLEVEL) #include @@ -57,11 +58,34 @@ typedef short ADL_SInt16; enum ADLMIDI_VolumeModels { ADLMIDI_VolumeModel_AUTO = 0, - ADLMIDI_VolumeModel_Generic, - ADLMIDI_VolumeModel_CMF, - ADLMIDI_VolumeModel_DMX, - ADLMIDI_VolumeModel_APOGEE, - ADLMIDI_VolumeModel_9X + ADLMIDI_VolumeModel_Generic = 1, + ADLMIDI_VolumeModel_NativeOPL3 = 2, + ADLMIDI_VolumeModel_CMF = ADLMIDI_VolumeModel_NativeOPL3, + ADLMIDI_VolumeModel_DMX = 3, + ADLMIDI_VolumeModel_APOGEE = 4, + ADLMIDI_VolumeModel_9X = 5 +}; + +enum ADLMIDI_SampleType +{ + ADLMIDI_SampleType_S16 = 0, /* signed PCM 16-bit */ + ADLMIDI_SampleType_S8, /* signed PCM 8-bit */ + ADLMIDI_SampleType_F32, /* float 32-bit */ + ADLMIDI_SampleType_F64, /* float 64-bit */ + ADLMIDI_SampleType_S24, /* signed PCM 24-bit */ + ADLMIDI_SampleType_S32, /* signed PCM 32-bit */ + ADLMIDI_SampleType_U8, /* unsigned PCM 8-bit */ + ADLMIDI_SampleType_U16, /* unsigned PCM 16-bit */ + ADLMIDI_SampleType_U24, /* unsigned PCM 24-bit */ + ADLMIDI_SampleType_U32, /* unsigned PCM 32-bit */ + ADLMIDI_SampleType_Count, +}; + +struct ADLMIDI_AudioFormat +{ + enum ADLMIDI_SampleType type; /* type of sample */ + unsigned containerSize; /* size in bytes of the storage type */ + unsigned sampleOffset; /* distance in bytes between consecutive samples */ }; struct ADL_MIDIPlayer @@ -87,6 +111,46 @@ extern int adl_getBanksCount(); /* Returns pointer to array of names of every bank */ extern const char *const *adl_getBankNames(); +/* Reference to dynamic bank */ +typedef struct ADL_Bank +{ + void *pointer[3]; +} ADL_Bank; + +/* Identifier of dynamic bank */ +typedef struct ADL_BankId +{ + ADL_UInt8 percussive, msb, lsb; +} ADL_BankId; + +/* Flags for dynamic bank access */ +enum ADL_BankAccessFlags +{ + ADLMIDI_Bank_Create = 1, /* create bank, allocating memory as needed */ + ADLMIDI_Bank_CreateRt = 1|2, /* create bank, never allocating memory */ +}; + +typedef struct ADL_Instrument ADL_Instrument; + +#if defined(ADLMIDI_UNSTABLE_API) +/* Preallocates a minimum number of bank slots. Returns the actual capacity. */ +extern int adl_reserveBanks(struct ADL_MIDIPlayer *device, unsigned banks); +/* Gets the bank designated by the identifier, optionally creating if it does not exist. */ +extern int adl_getBank(struct ADL_MIDIPlayer *device, const ADL_BankId *id, int flags, ADL_Bank *bank); +/* Gets the identifier of a bank. */ +extern int adl_getBankId(struct ADL_MIDIPlayer *device, const ADL_Bank *bank, ADL_BankId *id); +/* Removes a bank. */ +extern int adl_removeBank(struct ADL_MIDIPlayer *device, ADL_Bank *bank); +/* Gets the first bank. */ +extern int adl_getFirstBank(struct ADL_MIDIPlayer *device, ADL_Bank *bank); +/* Iterates to the next bank. */ +extern int adl_getNextBank(struct ADL_MIDIPlayer *device, ADL_Bank *bank); +/* Gets the nth intrument in the bank [0..127]. */ +extern int adl_getInstrument(struct ADL_MIDIPlayer *device, const ADL_Bank *bank, unsigned index, ADL_Instrument *ins); +/* Sets the nth intrument in the bank [0..127]. */ +extern int adl_setInstrument(struct ADL_MIDIPlayer *device, ADL_Bank *bank, unsigned index, const ADL_Instrument *ins); +#endif /* defined(ADLMIDI_UNSTABLE_API) */ + /*Sets number of 4-operator channels between all chips. By default, it is automatically re-calculating every bank change. If you want to specify custom number of four operator channels, @@ -109,10 +173,16 @@ extern void adl_setHTremolo(struct ADL_MIDIPlayer *device, int htremo); /*Override Enable(1) or Disable(0) scaling of modulator volumes. -1 - use bank default scaling of modulator volumes*/ extern void adl_setScaleModulators(struct ADL_MIDIPlayer *device, int smod); +/*Enable(1) or Disable(0) full-range brightness (MIDI CC74 used in XG music to filter result sounding) scaling. + By default, brightness affects sound between 0 and 64. + When this option is enabled, the range will use a full range from 0 up to 127. +*/ +extern void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *device, int fr_brightness); + /*Enable or disable built-in loop (built-in loop supports 'loopStart' and 'loopEnd' tags to loop specific part)*/ extern void adl_setLoopEnabled(struct ADL_MIDIPlayer *device, int loopEn); -/*Enable or disable Logariphmic volume changer */ +/* !!!DEPRECATED!!! Enable or disable Logariphmic volume changer */ extern void adl_setLogarithmicVolumes(struct ADL_MIDIPlayer *device, int logvol); /*Set different volume range model */ @@ -125,15 +195,33 @@ extern int adl_openBankFile(struct ADL_MIDIPlayer *device, const char *filePath) extern int adl_openBankData(struct ADL_MIDIPlayer *device, const void *mem, unsigned long size); -/*Returns name of currently used OPL3 emulator*/ +/* DEPRECATED */ extern const char *adl_emulatorName(); +/*Returns chip emulator name string*/ +extern const char *adl_chipEmulatorName(struct ADL_MIDIPlayer *device); + +enum ADL_Emulator +{ + ADLMIDI_EMU_NUKED = 0, + ADLMIDI_EMU_NUKED_174, + ADLMIDI_EMU_DOSBOX, + ADLMIDI_EMU_end +}; + +/* Switch the emulation core */ +extern int adl_switchEmulator(struct ADL_MIDIPlayer *device, int emulator); + + typedef struct { ADL_UInt16 major; ADL_UInt16 minor; ADL_UInt16 patch; } ADL_Version; +/*Run emulator with PCM rate to reduce CPU usage on slow devices. May decrease sounding accuracy.*/ +extern int adl_setRunAtPcmRate(struct ADL_MIDIPlayer *device, int enabled); + /*Returns string which contains a version number*/ extern const char *adl_linkedLibraryVersion(); @@ -213,11 +301,17 @@ extern struct Adl_MarkerEntry adl_metaMarker(struct ADL_MIDIPlayer *device, size /*Take a sample buffer and iterate MIDI timers */ -extern int adl_play(struct ADL_MIDIPlayer *device, int sampleCount, short out[]); +extern int adl_play(struct ADL_MIDIPlayer *device, int sampleCount, short *out); + +/*Take a sample buffer and iterate MIDI timers */ +extern int adl_playFormat(struct ADL_MIDIPlayer *device, int sampleCount, ADL_UInt8 *left, ADL_UInt8 *right, const struct ADLMIDI_AudioFormat *format); /*Generate audio output from chip emulators without iteration of MIDI timers.*/ extern int adl_generate(struct ADL_MIDIPlayer *device, int sampleCount, short *out); +/*Generate audio output from chip emulators without iteration of MIDI timers.*/ +extern int adl_generateFormat(struct ADL_MIDIPlayer *device, int sampleCount, ADL_UInt8 *left, ADL_UInt8 *right, const struct ADLMIDI_AudioFormat *format); + /** * @brief Periodic tick handler. * @param device @@ -286,6 +380,70 @@ extern void adl_setNoteHook(struct ADL_MIDIPlayer *device, ADL_NoteHook noteHook /* Set debug message hook */ extern void adl_setDebugMessageHook(struct ADL_MIDIPlayer *device, ADL_DebugMessageHook debugMessageHook, void *userData); + +/**Instrument structures**/ + +enum +{ + ADLMIDI_InstrumentVersion = 0, +}; + +typedef enum ADL_InstrumentFlags +{ + /* Is two-operator single-voice instrument (no flags) */ + ADLMIDI_Ins_2op = 0x00, + /* Is true four-operator instrument */ + ADLMIDI_Ins_4op = 0x01, + /* Is pseudo four-operator (two 2-operator voices) instrument */ + ADLMIDI_Ins_Pseudo4op = 0x02, + /* Is a blank instrument entry */ + ADLMIDI_Ins_IsBlank = 0x04, + /* Mask of the flags range */ + ADLMIDI_Ins_ALL_MASK = 0x07, +} ADL_InstrumentFlags; + +typedef struct ADL_Operator +{ + /* AM/Vib/Env/Ksr/FMult characteristics */ + ADL_UInt8 avekf_20; + /* Key Scale Level / Total level register data */ + ADL_UInt8 ksl_l_40; + /* Attack / Decay */ + ADL_UInt8 atdec_60; + /* Systain and Release register data */ + ADL_UInt8 susrel_80; + /* Wave form */ + ADL_UInt8 waveform_E0; +} ADL_Operator; + +typedef struct ADL_Instrument +{ + /* Version of the instrument object */ + int version; + /* MIDI note key (half-tone) offset for an instrument (or a first voice in pseudo-4-op mode) */ + ADL_SInt16 note_offset1; + /* MIDI note key (half-tone) offset for a second voice in pseudo-4-op mode */ + ADL_SInt16 note_offset2; + /* MIDI note velocity offset (taken from Apogee TMB format) */ + ADL_SInt8 midi_velocity_offset; + /* Second voice detune level (taken from DMX OP2) */ + ADL_SInt8 second_voice_detune; + /* Percussion MIDI base tone number at which this drum will be played */ + ADL_UInt8 percussion_key_number; + /* Enum ADL_InstrumentFlags */ + ADL_UInt8 inst_flags; + /* Feedback&Connection register for first and second operators */ + ADL_UInt8 fb_conn1_C0; + /* Feedback&Connection register for third and fourth operators */ + ADL_UInt8 fb_conn2_C0; + /* Operators register data */ + ADL_Operator operators[4]; + /* Millisecond delay of sounding while key is on */ + ADL_UInt16 delay_on_ms; + /* Millisecond delay of sounding after key off */ + ADL_UInt16 delay_off_ms; +} ADL_Instrument; + #ifdef __cplusplus } #endif diff --git a/src/sound/adlmidi/adlmidi.hpp b/src/sound/adlmidi/adlmidi.hpp index 63f2abd48..6d01b8d33 100644 --- a/src/sound/adlmidi/adlmidi.hpp +++ b/src/sound/adlmidi/adlmidi.hpp @@ -24,24 +24,15 @@ #ifndef ADLMIDI_HPP #define ADLMIDI_HPP -#include "adlmidi.h" - -#include -#include - -class OPL3; -class MIDIplay; +struct ADL_MIDIPlayer; class AdlInstrumentTester { - uint32_t cur_gm; - uint32_t ins_idx; - std::vector adl_ins_list; - OPL3 *opl; - MIDIplay * play; + struct Impl; + Impl *P; public: - AdlInstrumentTester(ADL_MIDIPlayer *device); + explicit AdlInstrumentTester(ADL_MIDIPlayer *device); virtual ~AdlInstrumentTester(); // Find list of adlib instruments that supposedly implement this GM @@ -51,6 +42,10 @@ public: void NextGM(int offset); void NextAdl(int offset); bool HandleInputChar(char ch); + +private: + AdlInstrumentTester(const AdlInstrumentTester &); + AdlInstrumentTester &operator=(const AdlInstrumentTester &); }; #endif //ADLMIDI_HPP diff --git a/src/sound/adlmidi/adlmidi_bankmap.h b/src/sound/adlmidi/adlmidi_bankmap.h new file mode 100644 index 000000000..e4534cd6e --- /dev/null +++ b/src/sound/adlmidi/adlmidi_bankmap.h @@ -0,0 +1,127 @@ +/* + * libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation + * + * Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma + * ADLMIDI Library API: Copyright (c) 2015-2018 Vitaly Novichkov + * + * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation: + * http://iki.fi/bisqwit/source/adlmidi.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ADLMIDI_BANKMAP_H +#define ADLMIDI_BANKMAP_H + +#include +#include +#include +#include + +#include "adlmidi_ptr.hpp" + +/** + * A simple hash map which accepts bank numbers as keys, can be reserved to a + * fixed size, offers O(1) search and insertion, has a hash function to + * optimize for the worst case, and has some good cache locality properties. + */ +template +class BasicBankMap +{ +public: + typedef uint16_t key_type; /* the bank identifier */ + typedef T mapped_type; + typedef std::pair value_type; + + BasicBankMap(); + void reserve(size_t capacity); + + size_t size() const + { return m_size; } + size_t capacity() const + { return m_capacity; } + bool empty() const + { return m_size == 0; } + + class iterator; + iterator begin() const; + iterator end() const; + + struct do_not_expand_t {}; + + iterator find(key_type key); + void erase(iterator it); + std::pair insert(const value_type &value); + std::pair insert(const value_type &value, do_not_expand_t); + void clear(); + + T &operator[](key_type key); + +private: + struct Slot; + enum { minimum_allocation = 4 }; + enum + { + hash_bits = 8, /* worst case # of collisions: 128^2/2^hash_bits */ + hash_buckets = 1 << hash_bits, + }; + +public: + class iterator + { + public: + iterator(); + value_type &operator*() const { return slot->value; } + value_type *operator->() const { return &slot->value; } + iterator &operator++(); + bool operator==(const iterator &o) const; + bool operator!=(const iterator &o) const; + void to_ptrs(void *ptrs[3]); + static iterator from_ptrs(void *const ptrs[3]); + private: + Slot **buckets; + Slot *slot; + size_t index; + iterator(Slot **buckets, Slot *slot, size_t index); +#ifdef _MSC_VER + template + friend class BasicBankMap; +#else + friend class BasicBankMap; +#endif + }; + +private: + struct Slot { + Slot *next, *prev; + value_type value; + Slot() : next(NULL), prev(NULL) {} + }; + AdlMIDI_SPtrArray m_buckets; + std::list< AdlMIDI_SPtrArray > m_allocations; + Slot *m_freeslots; + size_t m_size; + size_t m_capacity; + static size_t hash(key_type key); + Slot *allocate_slot(); + Slot *ensure_allocate_slot(); + void free_slot(Slot *slot); + Slot *bucket_find(size_t index, key_type key); + void bucket_add(size_t index, Slot *slot); + void bucket_remove(size_t index, Slot *slot); +}; + +#include "adlmidi_bankmap.tcc" + +#endif // ADLMIDI_BANKMAP_H diff --git a/src/sound/adlmidi/adlmidi_bankmap.tcc b/src/sound/adlmidi/adlmidi_bankmap.tcc new file mode 100644 index 000000000..76e70016c --- /dev/null +++ b/src/sound/adlmidi/adlmidi_bankmap.tcc @@ -0,0 +1,283 @@ +/* + * libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation + * + * Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma + * ADLMIDI Library API: Copyright (c) 2015-2018 Vitaly Novichkov + * + * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation: + * http://iki.fi/bisqwit/source/adlmidi.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "adlmidi_bankmap.h" +#include + +template +inline BasicBankMap::BasicBankMap() + : m_freeslots(NULL), + m_size(0), + m_capacity(0) +{ + m_buckets.reset(new Slot *[hash_buckets]()); +} + +template +inline size_t BasicBankMap::hash(key_type key) +{ + // disregard the 0 high bit in LSB + key = (key & 127) | ((key >> 8) << 7); + // take low part as hash value + return key & (hash_buckets - 1); +} + +template +void BasicBankMap::reserve(size_t capacity) +{ + if(m_capacity >= capacity) + return; + + size_t need = capacity - m_capacity; + const size_t minalloc = static_cast(minimum_allocation); + need = (need < minalloc) ? minalloc : need; + + AdlMIDI_SPtrArray slotz; + slotz.reset(new Slot[need]); + m_allocations.push_back(slotz); + m_capacity += need; + + for(size_t i = need; i-- > 0;) + free_slot(&slotz[i]); +} + +template +typename BasicBankMap::iterator +BasicBankMap::begin() const +{ + iterator it(m_buckets.get(), NULL, 0); + while(it.index < hash_buckets && !(it.slot = m_buckets[it.index])) + ++it.index; + return it; +} + +template +typename BasicBankMap::iterator +BasicBankMap::end() const +{ + iterator it(m_buckets.get(), NULL, hash_buckets); + return it; +} + +template +typename BasicBankMap::iterator BasicBankMap::find(key_type key) +{ + size_t index = hash(key); + Slot *slot = bucket_find(index, key); + if(!slot) + return end(); + return iterator(m_buckets.get(), slot, index); +} + +template +void BasicBankMap::erase(iterator it) +{ + bucket_remove(it.index, it.slot); + free_slot(it.slot); + --m_size; +} + +template +inline BasicBankMap::iterator::iterator() + : buckets(NULL), slot(NULL), index(0) +{ +} + +template +inline BasicBankMap::iterator::iterator(Slot **buckets, Slot *slot, size_t index) + : buckets(buckets), slot(slot), index(index) +{ +} + +template +typename BasicBankMap::iterator & +BasicBankMap::iterator::operator++() +{ + if(slot->next) + slot = slot->next; + else { + Slot *slot = NULL; + ++index; + while(index < hash_buckets && !(slot = buckets[index])) + ++index; + this->slot = slot; + } + return *this; +} + +template +bool BasicBankMap::iterator::operator==(const iterator &o) const +{ + return buckets == o.buckets && slot == o.slot && index == o.index; +} + +template +inline bool BasicBankMap::iterator::operator!=(const iterator &o) const +{ + return !operator==(o); +} + +template +void BasicBankMap::iterator::to_ptrs(void *ptrs[3]) +{ + ptrs[0] = buckets; + ptrs[1] = slot; + ptrs[2] = (void *)index; +} + +template +typename BasicBankMap::iterator +BasicBankMap::iterator::from_ptrs(void *const ptrs[3]) +{ + iterator it; + it.buckets = (Slot **)ptrs[0]; + it.slot = (Slot *)ptrs[1]; + it.index = (size_t)ptrs[2]; + return it; +} + +template +std::pair::iterator, bool> +BasicBankMap::insert(const value_type &value) +{ + size_t index = hash(value.first); + Slot *slot = bucket_find(index, value.first); + if(slot) + return std::make_pair(iterator(m_buckets.get(), slot, index), false); + slot = allocate_slot(); + if(!slot) { + reserve(m_capacity + minimum_allocation); + slot = ensure_allocate_slot(); + } + slot->value = value; + bucket_add(index, slot); + ++m_size; + return std::make_pair(iterator(m_buckets.get(), slot, index), true); +} + +template +std::pair::iterator, bool> +BasicBankMap::insert(const value_type &value, do_not_expand_t) +{ + size_t index = hash(value.first); + Slot *slot = bucket_find(index, value.first); + if(slot) + return std::make_pair(iterator(m_buckets.get(), slot, index), false); + slot = allocate_slot(); + if(!slot) + return std::make_pair(end(), false); + slot->value = value; + bucket_add(index, slot); + ++m_size; + return std::make_pair(iterator(m_buckets.get(), slot, index), true); +} + +template +void BasicBankMap::clear() +{ + for(size_t i = 0; i < hash_buckets; ++i) { + Slot *slot = m_buckets[i]; + while (Slot *cur = slot) { + slot = slot->next; + free_slot(cur); + } + m_buckets[i] = NULL; + } + m_size = 0; +} + +template +inline T &BasicBankMap::operator[](key_type key) +{ + return insert(value_type(key, T())).first->second; +} + +template +typename BasicBankMap::Slot * +BasicBankMap::allocate_slot() +{ + Slot *slot = m_freeslots; + if(!slot) + return NULL; + Slot *next = slot->next; + if(next) + next->prev = NULL; + m_freeslots = next; + return slot; +} + +template +inline typename BasicBankMap::Slot * +BasicBankMap::ensure_allocate_slot() +{ + Slot *slot = allocate_slot(); + assert(slot); + return slot; +} + +template +void BasicBankMap::free_slot(Slot *slot) +{ + Slot *next = m_freeslots; + if(next) + next->prev = slot; + slot->prev = NULL; + slot->next = next; + m_freeslots = slot; + m_freeslots->value.second = T(); +} + +template +typename BasicBankMap::Slot * +BasicBankMap::bucket_find(size_t index, key_type key) +{ + Slot *slot = m_buckets[index]; + while(slot && slot->value.first != key) + slot = slot->next; + return slot; +} + +template +void BasicBankMap::bucket_add(size_t index, Slot *slot) +{ + assert(slot); + Slot *next = m_buckets[index]; + if(next) + next->prev = slot; + slot->next = next; + m_buckets[index] = slot; +} + +template +void BasicBankMap::bucket_remove(size_t index, Slot *slot) +{ + assert(slot); + Slot *prev = slot->prev; + Slot *next = slot->next; + if(!prev) + m_buckets[index] = next; + else + prev->next = next; + if(next) + next->prev = prev; +} diff --git a/src/sound/adlmidi/adlmidi_load.cpp b/src/sound/adlmidi/adlmidi_load.cpp index 00a4ce3de..7f69e259f 100644 --- a/src/sound/adlmidi/adlmidi_load.cpp +++ b/src/sound/adlmidi/adlmidi_load.cpp @@ -22,6 +22,7 @@ */ #include "adlmidi_private.hpp" +#include "wopl/wopl_file.h" #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER # ifndef ADLMIDI_DISABLE_MUS_SUPPORT @@ -32,6 +33,7 @@ # endif//XMI #endif //ADLMIDI_DISABLE_MIDI_SEQUENCER +#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER uint64_t MIDIplay::ReadBEint(const void *buffer, size_t nbytes) { uint64_t result = 0; @@ -54,6 +56,8 @@ uint64_t MIDIplay::ReadLEint(const void *buffer, size_t nbytes) return result; } +#endif + bool MIDIplay::LoadBank(const std::string &filename) { fileReader file; @@ -68,282 +72,223 @@ bool MIDIplay::LoadBank(const void *data, size_t size) return LoadBank(file); } - - -/* WOPL-needed misc functions */ -static uint16_t toUint16LE(const uint8_t *arr) +template +static void cvt_generic_to_FMIns(adlinsdata2 &ins, const WOPLI &in) { - uint16_t num = arr[0]; - num |= ((arr[1] << 8) & 0xFF00); - return num; -} - -static uint16_t toUint16BE(const uint8_t *arr) -{ - uint16_t num = arr[1]; - num |= ((arr[0] << 8) & 0xFF00); - return num; -} - -static int16_t toSint16BE(const uint8_t *arr) -{ - int16_t num = *reinterpret_cast(&arr[0]); - num *= 1 << 8; - num |= arr[1]; - return num; -} - -static const char *wopl3_magic = "WOPL3-BANK\0"; -static const uint16_t wopl_latest_version = 3; - -#define WOPL_INST_SIZE_V2 62 -#define WOPL_INST_SIZE_V3 66 - -enum WOPL_InstrumentFlags -{ - WOPL_Flags_NONE = 0, - WOPL_Flag_Enable4OP = 0x01, - WOPL_Flag_Pseudo4OP = 0x02, - WOPL_Flag_NoSound = 0x04, -}; - -struct WOPL_Inst -{ - bool fourOps; - char padding[7]; - struct adlinsdata adlins; - struct adldata op[2]; - uint16_t ms_sound_kon; - uint16_t ms_sound_koff; -}; - -static bool readInstrument(MIDIplay::fileReader &file, WOPL_Inst &ins, uint16_t &version, bool isPercussion = false) -{ - uint8_t idata[WOPL_INST_SIZE_V3]; - if(version >= 3) - { - if(file.read(idata, 1, WOPL_INST_SIZE_V3) != WOPL_INST_SIZE_V3) - return false; - } - else - { - if(file.read(idata, 1, WOPL_INST_SIZE_V2) != WOPL_INST_SIZE_V2) - return false; - } - - //strncpy(ins.name, char_p(idata), 32); - ins.op[0].finetune = (int8_t)toSint16BE(idata + 32); - ins.op[1].finetune = (int8_t)toSint16BE(idata + 34); - //ins.velocity_offset = int8_t(idata[36]); - - ins.adlins.voice2_fine_tune = 0.0; - int8_t voice2_fine_tune = int8_t(idata[37]); + ins.voice2_fine_tune = 0.0; + int8_t voice2_fine_tune = in.second_voice_detune; if(voice2_fine_tune != 0) { if(voice2_fine_tune == 1) - ins.adlins.voice2_fine_tune = 0.000025; + ins.voice2_fine_tune = 0.000025; else if(voice2_fine_tune == -1) - ins.adlins.voice2_fine_tune = -0.000025; + ins.voice2_fine_tune = -0.000025; else - ins.adlins.voice2_fine_tune = ((voice2_fine_tune * 15.625) / 1000.0); + ins.voice2_fine_tune = voice2_fine_tune * (15.625 / 1000.0); } - ins.adlins.tone = isPercussion ? idata[38] : 0; + ins.tone = in.percussion_key_number; + ins.flags = (in.inst_flags & WOPL_Ins_4op) && (in.inst_flags & WOPL_Ins_Pseudo4op) ? adlinsdata::Flag_Pseudo4op : 0; + ins.flags|= (in.inst_flags & WOPL_Ins_4op) && ((in.inst_flags & WOPL_Ins_Pseudo4op) == 0) ? adlinsdata::Flag_Real4op : 0; + ins.flags|= (in.inst_flags & WOPL_Ins_IsBlank) ? adlinsdata::Flag_NoSound : 0; - uint8_t flags = idata[39]; - ins.adlins.flags = (flags & WOPL_Flag_Enable4OP) && (flags & WOPL_Flag_Pseudo4OP) ? adlinsdata::Flag_Pseudo4op : 0; - ins.adlins.flags|= (flags & WOPL_Flag_NoSound) ? adlinsdata::Flag_NoSound : 0; - ins.fourOps = (flags & WOPL_Flag_Enable4OP) || (flags & WOPL_Flag_Pseudo4OP); - - ins.op[0].feedconn = (idata[40]); - ins.op[1].feedconn = (idata[41]); - - for(size_t op = 0, slt = 0; op < 4; op++, slt++) + bool fourOps = (in.inst_flags & WOPL_Ins_4op) || (in.inst_flags & WOPL_Ins_Pseudo4op); + for(size_t op = 0, slt = 0; op < static_cast(fourOps ? 4 : 2); op++, slt++) { - size_t off = 42 + size_t(op) * 5; - // ins.setAVEKM(op, idata[off + 0]);//AVEKM - // ins.setAtDec(op, idata[off + 2]);//AtDec - // ins.setSusRel(op, idata[off + 3]);//SusRel - // ins.setWaveForm(op, idata[off + 4]);//WaveForm - // ins.setKSLL(op, idata[off + 1]);//KSLL - ins.op[slt].carrier_E862 = - ((static_cast(idata[off + 4]) << 24) & 0xFF000000) //WaveForm - | ((static_cast(idata[off + 3]) << 16) & 0x00FF0000) //SusRel - | ((static_cast(idata[off + 2]) << 8) & 0x0000FF00) //AtDec - | ((static_cast(idata[off + 0]) << 0) & 0x000000FF); //AVEKM - ins.op[slt].carrier_40 = idata[off + 1];//KSLL + ins.adl[slt].carrier_E862 = + ((static_cast(in.operators[op].waveform_E0) << 24) & 0xFF000000) //WaveForm + | ((static_cast(in.operators[op].susrel_80) << 16) & 0x00FF0000) //SusRel + | ((static_cast(in.operators[op].atdec_60) << 8) & 0x0000FF00) //AtDec + | ((static_cast(in.operators[op].avekf_20) << 0) & 0x000000FF); //AVEKM + ins.adl[slt].carrier_40 = in.operators[op].ksl_l_40;//KSLL op++; - off = 42 + size_t(op) * 5; - ins.op[slt].modulator_E862 = - ((static_cast(idata[off + 4]) << 24) & 0xFF000000) //WaveForm - | ((static_cast(idata[off + 3]) << 16) & 0x00FF0000) //SusRel - | ((static_cast(idata[off + 2]) << 8) & 0x0000FF00) //AtDec - | ((static_cast(idata[off + 0]) << 0) & 0x000000FF); //AVEKM - ins.op[slt].modulator_40 = idata[off + 1];//KSLL + ins.adl[slt].modulator_E862 = + ((static_cast(in.operators[op].waveform_E0) << 24) & 0xFF000000) //WaveForm + | ((static_cast(in.operators[op].susrel_80) << 16) & 0x00FF0000) //SusRel + | ((static_cast(in.operators[op].atdec_60) << 8) & 0x0000FF00) //AtDec + | ((static_cast(in.operators[op].avekf_20) << 0) & 0x000000FF); //AVEKM + ins.adl[slt].modulator_40 = in.operators[op].ksl_l_40;//KSLL } - if(version >= 3) + ins.adl[0].finetune = static_cast(in.note_offset1); + ins.adl[0].feedconn = in.fb_conn1_C0; + if(!fourOps) + ins.adl[1] = ins.adl[0]; + else { - ins.ms_sound_kon = toUint16BE(idata + 62); - ins.ms_sound_koff = toUint16BE(idata + 64); + ins.adl[1].finetune = static_cast(in.note_offset2); + ins.adl[1].feedconn = in.fb_conn2_C0; + } + + ins.ms_sound_kon = in.delay_on_ms; + ins.ms_sound_koff = in.delay_off_ms; +} + +template +static void cvt_FMIns_to_generic(WOPLI &ins, const adlinsdata2 &in) +{ + ins.second_voice_detune = 0; + double voice2_fine_tune = in.voice2_fine_tune; + if(voice2_fine_tune != 0) + { + if(voice2_fine_tune > 0 && voice2_fine_tune <= 0.000025) + ins.second_voice_detune = 1; + else if(voice2_fine_tune < 0 && voice2_fine_tune >= -0.000025) + ins.second_voice_detune = -1; + else + { + long value = lround(voice2_fine_tune * (1000.0 / 15.625)); + value = (value < -128) ? -128 : value; + value = (value > +127) ? +127 : value; + ins.second_voice_detune = static_cast(value); + } + } + + ins.percussion_key_number = in.tone; + bool fourOps = (in.flags & adlinsdata::Flag_Pseudo4op) || in.adl[0] != in.adl[1]; + ins.inst_flags = fourOps ? WOPL_Ins_4op : 0; + ins.inst_flags|= (in.flags & adlinsdata::Flag_Pseudo4op) ? WOPL_Ins_Pseudo4op : 0; + ins.inst_flags|= (in.flags & adlinsdata::Flag_NoSound) ? WOPL_Ins_IsBlank : 0; + + for(size_t op = 0, slt = 0; op < static_cast(fourOps ? 4 : 2); op++, slt++) + { + ins.operators[op].waveform_E0 = static_cast(in.adl[slt].carrier_E862 >> 24); + ins.operators[op].susrel_80 = static_cast(in.adl[slt].carrier_E862 >> 16); + ins.operators[op].atdec_60 = static_cast(in.adl[slt].carrier_E862 >> 8); + ins.operators[op].avekf_20 = static_cast(in.adl[slt].carrier_E862 >> 0); + ins.operators[op].ksl_l_40 = in.adl[slt].carrier_40; + + op++; + ins.operators[op].waveform_E0 = static_cast(in.adl[slt].carrier_E862 >> 24); + ins.operators[op].susrel_80 = static_cast(in.adl[slt].carrier_E862 >> 16); + ins.operators[op].atdec_60 = static_cast(in.adl[slt].carrier_E862 >> 8); + ins.operators[op].avekf_20 = static_cast(in.adl[slt].carrier_E862 >> 0); + ins.operators[op].ksl_l_40 = in.adl[slt].carrier_40; + } + + ins.note_offset1 = in.adl[0].finetune; + ins.fb_conn1_C0 = in.adl[0].feedconn; + if(!fourOps) + { + ins.operators[2] = ins.operators[0]; + ins.operators[3] = ins.operators[1]; } else { - ins.ms_sound_kon = 1000; - ins.ms_sound_koff = 500; + ins.note_offset2 = in.adl[1].finetune; + ins.fb_conn2_C0 = in.adl[1].feedconn; } - return true; + ins.delay_on_ms = in.ms_sound_kon; + ins.delay_off_ms = in.ms_sound_koff; +} + +void cvt_ADLI_to_FMIns(adlinsdata2 &ins, const ADL_Instrument &in) +{ + return cvt_generic_to_FMIns(ins, in); +} + +void cvt_FMIns_to_ADLI(ADL_Instrument &ins, const adlinsdata2 &in) +{ + cvt_FMIns_to_generic(ins, in); } bool MIDIplay::LoadBank(MIDIplay::fileReader &fr) { + int err = 0; + WOPLFile *wopl = NULL; + char *raw_file_data = NULL; size_t fsize; - ADL_UNUSED(fsize); if(!fr.isValid()) { errorStringOut = "Custom bank: Invalid data stream!"; return false; } - char magic[32]; - std::memset(magic, 0, 32); - - uint16_t version = 0; - - uint16_t count_melodic_banks = 1; - uint16_t count_percusive_banks = 1; - - if(fr.read(magic, 1, 11) != 11) + // Read complete bank file into the memory + fr.seek(0, SEEK_END); + fsize = fr.tell(); + fr.seek(0, SEEK_SET); + // Allocate necessary memory block + raw_file_data = (char*)malloc(fsize); + if(!raw_file_data) { - errorStringOut = "Custom bank: Can't read magic number!"; + errorStringOut = "Custom bank: Out of memory before of read!"; return false; } + fr.read(raw_file_data, 1, fsize); - if(std::strncmp(magic, wopl3_magic, 11) != 0) + // Parse bank file from the memory + wopl = WOPL_LoadBankFromMem((void*)raw_file_data, fsize, &err); + //Free the buffer no more needed + free(raw_file_data); + + // Check for any erros + if(!wopl) { - errorStringOut = "Custom bank: Invalid magic number!"; - return false; + switch(err) + { + case WOPL_ERR_BAD_MAGIC: + errorStringOut = "Custom bank: Invalid magic!"; + return false; + case WOPL_ERR_UNEXPECTED_ENDING: + errorStringOut = "Custom bank: Unexpected ending!"; + return false; + case WOPL_ERR_INVALID_BANKS_COUNT: + errorStringOut = "Custom bank: Invalid banks count!"; + return false; + case WOPL_ERR_NEWER_VERSION: + errorStringOut = "Custom bank: Version is newer than supported by this library!"; + return false; + case WOPL_ERR_OUT_OF_MEMORY: + errorStringOut = "Custom bank: Out of memory!"; + return false; + default: + errorStringOut = "Custom bank: Unknown error!"; + return false; + } } - uint8_t version_raw[2]; - if(fr.read(version_raw, 1, 2) != 2) - { - errorStringOut = "Custom bank: Can't read version!"; - return false; - } - - version = toUint16LE(version_raw); - if(version > wopl_latest_version) - { - errorStringOut = "Custom bank: Unsupported WOPL version!"; - return false; - } - - uint8_t head[6]; - std::memset(head, 0, 6); - if(fr.read(head, 1, 6) != 6) - { - errorStringOut = "Custom bank: Can't read header!"; - return false; - } - - count_melodic_banks = toUint16BE(head); - count_percusive_banks = toUint16BE(head + 2); - - if((count_melodic_banks < 1) || (count_percusive_banks < 1)) - { - errorStringOut = "Custom bank: Too few banks in this file!"; - return false; - } - - /*UNUSED YET*/ - bool default_deep_vibrato = ((head[4]>>0) & 0x01); - bool default_deep_tremolo = ((head[4]>>1) & 0x01); - - //5'th byte reserved for Deep-Tremolo and Deep-Vibrato flags - m_setup.HighTremoloMode = default_deep_tremolo; - m_setup.HighVibratoMode = default_deep_vibrato; - //6'th byte reserved for ADLMIDI's default volume model - m_setup.VolumeModel = (int)head[5]; - - opl.dynamic_melodic_banks.clear(); - opl.dynamic_percussion_banks.clear(); + opl.dynamic_bank_setup.adLibPercussions = false; + opl.dynamic_bank_setup.scaleModulators = false; + opl.dynamic_bank_setup.deepTremolo = (wopl->opl_flags & WOPL_FLAG_DEEP_TREMOLO) != 0; + opl.dynamic_bank_setup.deepVibrato = (wopl->opl_flags & WOPL_FLAG_DEEP_VIBRATO) != 0; + opl.dynamic_bank_setup.volumeModel = wopl->volume_model; + m_setup.HighTremoloMode = -1; + m_setup.HighVibratoMode = -1; + m_setup.VolumeModel = ADLMIDI_VolumeModel_AUTO; opl.setEmbeddedBank(m_setup.AdlBank); - if(version >= 2)//Read bank meta-entries + uint16_t slots_counts[2] = {wopl->banks_count_melodic, wopl->banks_count_percussion}; + WOPLBank *slots_src_ins[2] = { wopl->banks_melodic, wopl->banks_percussive }; + + for(unsigned ss = 0; ss < 2; ss++) { - for(uint16_t i = 0; i < count_melodic_banks; i++) + for(unsigned i = 0; i < slots_counts[ss]; i++) { - uint8_t bank_meta[34]; - if(fr.read(bank_meta, 1, 34) != 34) + unsigned bankno = + (slots_src_ins[ss][i].bank_midi_msb * 256) + + slots_src_ins[ss][i].bank_midi_lsb + + (ss ? OPL3::PercussionTag : 0); + OPL3::Bank &bank = opl.dynamic_banks[bankno]; + for(int j = 0; j < 128; j++) { - errorStringOut = "Custom bank: Fail to read melodic bank meta-data!"; - return false; + adlinsdata2 &ins = bank.ins[j]; + std::memset(&ins, 0, sizeof(adlinsdata2)); + WOPLInstrument &inIns = slots_src_ins[ss][i].ins[j]; + cvt_generic_to_FMIns(ins, inIns); } - uint16_t bank = uint16_t(bank_meta[33]) * 256 + uint16_t(bank_meta[32]); - size_t offset = opl.dynamic_melodic_banks.size(); - opl.dynamic_melodic_banks[bank] = offset; - //strncpy(bankMeta.name, char_p(bank_meta), 32); } - - for(uint16_t i = 0; i < count_percusive_banks; i++) - { - uint8_t bank_meta[34]; - if(fr.read(bank_meta, 1, 34) != 34) - { - errorStringOut = "Custom bank: Fail to read percussion bank meta-data!"; - return false; - } - uint16_t bank = uint16_t(bank_meta[33]) * 256 + uint16_t(bank_meta[32]); - size_t offset = opl.dynamic_percussion_banks.size(); - opl.dynamic_percussion_banks[bank] = offset; - //strncpy(bankMeta.name, char_p(bank_meta), 32); - } - } - - uint16_t total = 128 * count_melodic_banks; - bool readPercussion = false; - -tryAgain: - for(uint16_t i = 0; i < total; i++) - { - WOPL_Inst ins; - std::memset(&ins, 0, sizeof(WOPL_Inst)); - if(!readInstrument(fr, ins, version, readPercussion)) - { - opl.setEmbeddedBank(m_setup.AdlBank); - errorStringOut = "Custom bank: Fail to read instrument!"; - return false; - } - ins.adlins.ms_sound_kon = ins.ms_sound_kon; - ins.adlins.ms_sound_koff = ins.ms_sound_koff; - ins.adlins.adlno1 = static_cast(opl.dynamic_instruments.size() | opl.DynamicInstrumentTag); - opl.dynamic_instruments.push_back(ins.op[0]); - ins.adlins.adlno2 = ins.adlins.adlno1; - if(ins.fourOps) - { - ins.adlins.adlno2 = static_cast(opl.dynamic_instruments.size() | opl.DynamicInstrumentTag); - opl.dynamic_instruments.push_back(ins.op[1]); - } - opl.dynamic_metainstruments.push_back(ins.adlins); - } - - if(!readPercussion) - { - total = 128 * count_percusive_banks; - readPercussion = true; - goto tryAgain; } opl.AdlBank = ~0u; // Use dynamic banks! //Percussion offset is count of instruments multipled to count of melodic banks - opl.dynamic_percussion_offset = 128 * count_melodic_banks; - applySetup(); + WOPL_Free(wopl); + return true; } @@ -373,7 +318,7 @@ bool MIDIplay::LoadMIDI(MIDIplay::fileReader &fr) errorString.clear(); #ifdef DISABLE_EMBEDDED_BANKS - if((opl.AdlBank != ~0u) || (opl.dynamic_metainstruments.size() < 256)) + if((opl.AdlBank != ~0u) || opl.dynamic_banks.empty()) { errorStringOut = "Bank is not set! Please load any instruments bank by using of adl_openBankFile() or adl_openBankData() functions!"; return false; @@ -497,8 +442,7 @@ riffskip: #endif //ADLMIDI_DISABLE_XMI_SUPPORT else if(std::memcmp(HeaderBuf, "CTMF", 4) == 0) { - opl.dynamic_instruments.clear(); - opl.dynamic_metainstruments.clear(); + opl.dynamic_banks.clear(); // Creative Music Format (CMF). // When playing CTMF files, use the following commandline: // adlmidi song8.ctmf -p -v 1 1 0 @@ -520,13 +464,19 @@ riffskip: //std::printf("%u instruments\n", ins_count); for(unsigned i = 0; i < ins_count; ++i) { + unsigned bank = i / 256; + bank = (bank & 127) + ((bank >> 7) << 8); + if(bank > 127 + (127 << 8)) + break; + bank += (i % 256 < 128) ? 0 : OPL3::PercussionTag; + unsigned char InsData[16]; fr.read(InsData, 1, 16); /*std::printf("Ins %3u: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", i, InsData[0],InsData[1],InsData[2],InsData[3], InsData[4],InsData[5],InsData[6],InsData[7], InsData[8],InsData[9],InsData[10],InsData[11], InsData[12],InsData[13],InsData[14],InsData[15]);*/ - struct adldata adl; - struct adlinsdata adlins; + adlinsdata2 &adlins = opl.dynamic_banks[bank].ins[i % 128]; + adldata adl; adl.modulator_E862 = ((static_cast(InsData[8] & 0x07) << 24) & 0xFF000000) //WaveForm | ((static_cast(InsData[6]) << 16) & 0x00FF0000) //Sustain/Release @@ -541,15 +491,13 @@ riffskip: adl.carrier_40 = InsData[3]; adl.feedconn = InsData[10] & 0x0F; adl.finetune = 0; - adlins.adlno1 = static_cast(opl.dynamic_instruments.size() | opl.DynamicInstrumentTag); - adlins.adlno2 = adlins.adlno1; + adlins.adl[0] = adl; + adlins.adl[1] = adl; adlins.ms_sound_kon = 1000; adlins.ms_sound_koff = 500; adlins.tone = 0; adlins.flags = 0; adlins.voice2_fine_tune = 0.0; - opl.dynamic_metainstruments.push_back(adlins); - opl.dynamic_instruments.push_back(adl); } fr.seeku(mus_start, SEEK_SET); @@ -557,10 +505,9 @@ riffskip: DeltaTicks = (size_t)ticks; opl.AdlBank = ~0u; // Ignore AdlBank number, use dynamic banks instead //std::printf("CMF deltas %u ticks %u, basictempo = %u\n", deltas, ticks, basictempo); - opl.LogarithmicVolumes = true; opl.AdlPercussionMode = true; opl.m_musicMode = OPL3::MODE_CMF; - opl.m_volumeScale = OPL3::VOLUME_CMF; + opl.m_volumeScale = OPL3::VOLUME_NATIVE; } else { @@ -575,10 +522,9 @@ riffskip: fr.seek(0x7D, SEEK_SET); TrackCount = 1; DeltaTicks = 60; - opl.LogarithmicVolumes = true; //opl.CartoonersVolumes = true; opl.m_musicMode = OPL3::MODE_RSXX; - opl.m_volumeScale = OPL3::VOLUME_CMF; + opl.m_volumeScale = OPL3::VOLUME_NATIVE; } } @@ -636,11 +582,11 @@ riffskip: TrackData.clear(); TrackData.resize(TrackCount, std::vector()); - //CurrentPosition.track.clear(); - //CurrentPosition.track.resize(TrackCount); InvDeltaTicks = fraction(1, 1000000l * static_cast(DeltaTicks)); - //Tempo = 1000000l * InvDeltaTicks; - Tempo = fraction(1, static_cast(DeltaTicks)); + if(is_CMF || is_RSXX) + Tempo = fraction(1, static_cast(DeltaTicks)); + else + Tempo = fraction(1, static_cast(DeltaTicks) * 2); static const unsigned char EndTag[4] = {0xFF, 0x2F, 0x00, 0x00}; size_t totalGotten = 0; @@ -761,14 +707,14 @@ riffskip: return false; } - //Build new MIDI events table (ALPHA!!!) + //Build new MIDI events table if(!buildTrackData()) { errorStringOut = fr._fileName + ": MIDI data parsing error has occouped!\n" + errorString; return false; } - opl.Reset(m_setup.PCM_RATE); // Reset AdLib + opl.Reset(m_setup.emulator, m_setup.PCM_RATE, this); // Reset OPL3 chip //opl.Reset(); // ...twice (just in case someone misprogrammed OPL3 previously) ch.clear(); ch.resize(opl.NumChannels); diff --git a/src/sound/adlmidi/adlmidi_midiplay.cpp b/src/sound/adlmidi/adlmidi_midiplay.cpp index 13e1008c0..89c1a73ad 100644 --- a/src/sound/adlmidi/adlmidi_midiplay.cpp +++ b/src/sound/adlmidi/adlmidi_midiplay.cpp @@ -25,7 +25,7 @@ // Mapping from MIDI volume level to OPL level value. -static const uint32_t DMX_volume_mapping_table[] = +static const uint8_t DMX_volume_mapping_table[128] = { 0, 1, 3, 5, 6, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, @@ -43,23 +43,6 @@ static const uint32_t DMX_volume_mapping_table[] = 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 123, 124, 124, 125, 125, 126, 126, 127, 127, - //Protection entries to avoid crash if value more than 127 - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, }; static const uint8_t W9X_volume_mapping_table[32] = @@ -117,18 +100,17 @@ inline bool isXgPercChannel(uint8_t msb, uint8_t lsb) void MIDIplay::AdlChannel::AddAge(int64_t ms) { - if(users.empty()) - koff_time_until_neglible = - std::max(int64_t(koff_time_until_neglible - ms), static_cast(-0x1FFFFFFFl)); + const int64_t neg = static_cast(-0x1FFFFFFFl); + if(users_empty()) + koff_time_until_neglible = std::max(int64_t(koff_time_until_neglible - ms), neg); else { koff_time_until_neglible = 0; - - for(users_t::iterator i = users.begin(); i != users.end(); ++i) + for(LocationData *i = users_first; i; i = i->next) { - i->second.kon_time_until_neglible = - std::max(i->second.kon_time_until_neglible - ms, static_cast(-0x1FFFFFFFl)); - i->second.vibdelay += ms; + if(!i->fixed_sustain) + i->kon_time_until_neglible = std::max(i->kon_time_until_neglible - ms, neg); + i->vibdelay += ms; } } } @@ -222,7 +204,9 @@ void MIDIplay::MidiTrackRow::sortEvents(bool *noteStates) j = noteOffs.erase(j); markAsOn.erase(note_i); continue; - } else { + } + else + { //When same row has many note-offs on same row //that means a zero-length note follows previous note //it must be shuted down @@ -451,17 +435,17 @@ bool MIDIplay::buildTrackData() if(track.empty()) continue;//Empty track is useless! - #ifdef DEBUG_TIME_CALCULATION +#ifdef DEBUG_TIME_CALCULATION std::fprintf(stdout, "\n============Track %" PRIuPTR "=============\n", tk); std::fflush(stdout); - #endif +#endif MidiTrackRow *posPrev = &(*(track.begin()));//First element for(MidiTrackQueue::iterator it = track.begin(); it != track.end(); it++) { - #ifdef DEBUG_TIME_CALCULATION +#ifdef DEBUG_TIME_CALCULATION bool tempoChanged = false; - #endif +#endif MidiTrackRow &pos = *it; if((posPrev != &pos) && //Skip first event (!tempos.empty()) && //Only when in-track tempo events are available @@ -507,9 +491,9 @@ bool MIDIplay::buildTrackData() //Apply next tempo currentTempo = points[j].tempo; - #ifdef DEBUG_TIME_CALCULATION +#ifdef DEBUG_TIME_CALCULATION tempoChanged = true; - #endif +#endif } //Then calculate time between last tempo change point and end point TempoChangePoint tailTempo = points.back(); @@ -552,10 +536,10 @@ bool MIDIplay::buildTrackData() loopEndTime = pos.time; } - #ifdef DEBUG_TIME_CALCULATION +#ifdef DEBUG_TIME_CALCULATION std::fprintf(stdout, "= %10" PRId64 " = %10f%s\n", pos.absPos, pos.time, tempoChanged ? " <----TEMPO CHANGED" : ""); std::fflush(stdout); - #endif +#endif abs_position += pos.delay; posPrev = &pos; @@ -575,7 +559,7 @@ bool MIDIplay::buildTrackData() //Resolve "hell of all times" of too short drum notes: //move too short percussion note-offs far far away as possible /********************************************************************************/ - #if 1 //Use this to record WAVEs for comparison before/after implementing of this +#if 1 //Use this to record WAVEs for comparison before/after implementing of this if(opl.m_musicMode == OPL3::MODE_MIDI)//Percussion fix is needed for MIDI only, not for IMF/RSXX or CMF { //! Minimal real time in seconds @@ -625,8 +609,8 @@ bool MIDIplay::buildTrackData() } bool percussion = (et->channel == 9) || - banks[et->channel] == 0x7E00 || //XG SFX1/SFX2 channel (16128 signed decimal) - banks[et->channel] == 0x7F00; //XG Percussion channel (16256 signed decimal) + banks[et->channel] == 0x7E00 || //XG SFX1/SFX2 channel (16128 signed decimal) + banks[et->channel] == 0x7F00; //XG Percussion channel (16256 signed decimal) if(!percussion) continue; @@ -687,7 +671,7 @@ bool MIDIplay::buildTrackData() #undef DRUM_NOTE_MIN_TIME #undef DRUM_NOTE_MIN_TICKS } - #endif +#endif return true; } @@ -695,7 +679,9 @@ bool MIDIplay::buildTrackData() MIDIplay::MIDIplay(unsigned long sampleRate): - cmf_percussion_mode(false) + cmf_percussion_mode(false), + m_arpeggioCounter(0), + m_audioTickCounter(0) #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER , fullSongTimeLength(0.0), postSongWaitDelay(1.0), @@ -710,6 +696,9 @@ MIDIplay::MIDIplay(unsigned long sampleRate): { devices.clear(); + m_setup.emulator = ADLMIDI_EMU_NUKED; + m_setup.runAtPcmRate = false; + m_setup.PCM_RATE = sampleRate; m_setup.mindelay = 1.0 / (double)m_setup.PCM_RATE; m_setup.maxdelay = 512.0 / (double)m_setup.PCM_RATE; @@ -725,6 +714,7 @@ MIDIplay::MIDIplay(unsigned long sampleRate): //m_setup.SkipForward = 0; m_setup.loopingIsEnabled = false; m_setup.ScaleModulators = -1; + m_setup.fullRangeBrightnessCC74 = false; m_setup.delay = 0.0; m_setup.carry = 0.0; m_setup.tick_skip_samples_delay = 0; @@ -737,26 +727,44 @@ MIDIplay::MIDIplay(unsigned long sampleRate): void MIDIplay::applySetup() { m_setup.tick_skip_samples_delay = 0; - opl.HighTremoloMode = m_setup.HighTremoloMode == -1 ? adlbanksetup[m_setup.AdlBank].deepTremolo : (bool)m_setup.HighTremoloMode; - opl.HighVibratoMode = m_setup.HighVibratoMode == -1 ? adlbanksetup[m_setup.AdlBank].deepVibrato : (bool)m_setup.HighVibratoMode; - opl.AdlPercussionMode = m_setup.AdlPercussionMode == -1 ? adlbanksetup[m_setup.AdlBank].adLibPercussions : (bool)m_setup.AdlPercussionMode; - opl.ScaleModulators = m_setup.ScaleModulators == -1 ? adlbanksetup[m_setup.AdlBank].scaleModulators : (bool)m_setup.ScaleModulators; - opl.LogarithmicVolumes = m_setup.LogarithmicVolumes; - //opl.CartoonersVolumes = false; + + opl.runAtPcmRate = m_setup.runAtPcmRate; + + if(opl.AdlBank != ~0u) + opl.dynamic_bank_setup = adlbanksetup[m_setup.AdlBank]; + + opl.HighTremoloMode = m_setup.HighTremoloMode < 0 ? + opl.dynamic_bank_setup.deepTremolo : + (m_setup.HighTremoloMode != 0); + opl.HighVibratoMode = m_setup.HighVibratoMode < 0 ? + opl.dynamic_bank_setup.deepVibrato : + (m_setup.HighVibratoMode != 0); + opl.AdlPercussionMode = m_setup.AdlPercussionMode < 0 ? + opl.dynamic_bank_setup.adLibPercussions : + (m_setup.AdlPercussionMode != 0); + opl.ScaleModulators = m_setup.ScaleModulators < 0 ? + opl.dynamic_bank_setup.scaleModulators : + (m_setup.ScaleModulators != 0); + if(m_setup.LogarithmicVolumes) + opl.ChangeVolumeRangesModel(ADLMIDI_VolumeModel_NativeOPL3); opl.m_musicMode = OPL3::MODE_MIDI; opl.ChangeVolumeRangesModel(static_cast(m_setup.VolumeModel)); if(m_setup.VolumeModel == ADLMIDI_VolumeModel_AUTO)//Use bank default volume model - opl.m_volumeScale = (OPL3::VolumesScale)adlbanksetup[m_setup.AdlBank].volumeModel; + opl.m_volumeScale = (OPL3::VolumesScale)opl.dynamic_bank_setup.volumeModel; opl.NumCards = m_setup.NumCards; opl.NumFourOps = m_setup.NumFourOps; cmf_percussion_mode = false; - opl.Reset(m_setup.PCM_RATE); + opl.Reset(m_setup.emulator, m_setup.PCM_RATE, this); ch.clear(); ch.resize(opl.NumChannels); + + // Reset the arpeggio counter + m_arpeggioCounter = 0; } +#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER uint64_t MIDIplay::ReadVarLen(uint8_t **ptr) { uint64_t result = 0; @@ -789,13 +797,12 @@ uint64_t MIDIplay::ReadVarLenEx(uint8_t **ptr, uint8_t *end, bool &ok) return result; } -#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER double MIDIplay::Tick(double s, double granularity) { s *= tempoMultiplier; - #ifdef ENABLE_BEGIN_SILENCE_SKIPPING +#ifdef ENABLE_BEGIN_SILENCE_SKIPPING if(CurrentPositionNew.began) - #endif +#endif CurrentPositionNew.wait -= s; CurrentPositionNew.absTimePosition += s; @@ -824,7 +831,7 @@ double MIDIplay::Tick(double s, double granularity) return CurrentPositionNew.wait; } -#endif +#endif /* ADLMIDI_DISABLE_MIDI_SEQUENCER */ void MIDIplay::TickIteratos(double s) { @@ -941,27 +948,19 @@ void MIDIplay::setTempo(double tempo) { tempoMultiplier = tempo; } -#endif +#endif /* ADLMIDI_DISABLE_MIDI_SEQUENCER */ void MIDIplay::realTime_ResetState() { for(size_t ch = 0; ch < Ch.size(); ch++) { MIDIchannel &chan = Ch[ch]; + chan.resetAllControllers(); chan.volume = (opl.m_musicMode == OPL3::MODE_RSXX) ? 127 : 100; - chan.expression = 127; - chan.panning = 0x30; - chan.vibrato = 0; - chan.sustain = 0; - chan.bend = 0.0; - chan.bendsense = 2 / 8192.0; chan.vibpos = 0.0; - chan.vibdepth = 0.5 / 127.0; - chan.vibdelay = 0; chan.lastlrpn = 0; chan.lastmrpn = 0; chan.nrpn = false; - chan.brightness = 127; NoteUpdate_All(uint16_t(ch), Upd_All); NoteUpdate_All(uint16_t(ch), Upd_Off); } @@ -969,13 +968,16 @@ void MIDIplay::realTime_ResetState() bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) { + if(note >= 128) + note = 127; + if((opl.m_musicMode == OPL3::MODE_RSXX) && (velocity != 0)) { // Check if this is just a note after-touch - MIDIchannel::activenoteiterator i = Ch[channel].activenotes.find(note); - if(i != Ch[channel].activenotes.end()) + MIDIchannel::activenoteiterator i = Ch[channel].activenotes_find(note); + if(i) { - i->second.vol = velocity; + i->vol = velocity; NoteUpdate(channel, i, Upd_Volume); return false; } @@ -991,14 +993,16 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) if(velocity == 0) return false; - size_t midiins = Ch[channel].patch; - bool isPercussion = (channel % 16 == 9); + MIDIchannel &midiChan = Ch[channel]; + + size_t midiins = midiChan.patch; + bool isPercussion = (channel % 16 == 9); bool isXgPercussion = false; uint16_t bank = 0; - if(Ch[channel].bank_msb || Ch[channel].bank_lsb) + if(midiChan.bank_msb || midiChan.bank_lsb) { - bank = (uint16_t(Ch[channel].bank_msb) * 256) + uint16_t(Ch[channel].bank_lsb); + bank = (uint16_t(midiChan.bank_msb) * 256) + uint16_t(midiChan.bank_lsb); //0x7E00 - XG SFX1/SFX2 channel (16128 signed decimal) //0x7F00 - XG Percussion channel (16256 signed decimal) if(bank == 0x7E00 || bank == 0x7F00) @@ -1006,7 +1010,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) //Let XG SFX1/SFX2 bank will have LSB==1 (128...255 range in WOPN file) //Let XG Percussion bank will use (0...127 range in WOPN file) bank = (uint16_t)midiins + ((bank == 0x7E00) ? 128 : 0); // MIDI instrument defines the patch - midiins = opl.dynamic_percussion_offset + note; // Percussion instrument + midiins = note; // Percussion instrument isXgPercussion = true; isPercussion = false; } @@ -1015,43 +1019,43 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) if(isPercussion) { bank = (uint16_t)midiins; // MIDI instrument defines the patch - midiins = opl.dynamic_percussion_offset + note; // Percussion instrument + midiins = note; // Percussion instrument } + if(isPercussion || isXgPercussion) + bank += OPL3::PercussionTag; + + const adlinsdata2 *ains = &OPL3::emptyInstrument; //Set bank bank - if(bank > 0) + const OPL3::Bank *bnk = NULL; + if((bank & ~(uint16_t)OPL3::PercussionTag) > 0) { - if(isPercussion || isXgPercussion) + OPL3::BankMap::iterator b = opl.dynamic_banks.find(bank); + if(b != opl.dynamic_banks.end()) + bnk = &b->second; + + if(bnk) + ains = &bnk->ins[midiins]; + else if(hooks.onDebugMessage) { - OPL3::BankMap::iterator b = opl.dynamic_percussion_banks.find(bank); - if(b != opl.dynamic_percussion_banks.end()) - midiins += b->second * 128; - else - if(hooks.onDebugMessage) - { - if(!caugh_missing_banks_melodic.count(bank)) - { - hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing percussion MIDI bank %i (patch %i)", channel, bank, midiins); - caugh_missing_banks_melodic.insert(bank); - } - } - } - else - { - OPL3::BankMap::iterator b = opl.dynamic_melodic_banks.find(bank); - if(b != opl.dynamic_melodic_banks.end()) - midiins += b->second * 128; - else - if(hooks.onDebugMessage) - { - if(!caugh_missing_banks_percussion.count(bank)) - { - hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing melodic MIDI bank %i (patch %i)", channel, bank, midiins); - caugh_missing_banks_percussion.insert(bank); - } - } + std::set &missing = (isPercussion || isXgPercussion) ? + caugh_missing_banks_percussion : caugh_missing_banks_melodic; + const char *text = (isPercussion || isXgPercussion) ? + "percussion" : "melodic"; + if(missing.insert(bank).second) + hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing %s MIDI bank %i (patch %i)", channel, text, bank, midiins); } } + //Or fall back to first bank + if(ains->flags & adlinsdata::Flag_NoSound) + { + OPL3::BankMap::iterator b = opl.dynamic_banks.find(bank & OPL3::PercussionTag); + if(b != opl.dynamic_banks.end()) + bnk = &b->second; + + if(bnk) + ains = &bnk->ins[midiins]; + } /* if(MidCh%16 == 9 || (midiins != 32 && midiins != 46 && midiins != 48 && midiins != 50)) @@ -1062,8 +1066,6 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) //if(midiins == 56) vol = vol*6/10; // HACK //int meta = banks[opl.AdlBank][midiins]; - size_t meta = opl.GetAdlMetaNumber(midiins); - const adlinsdata *ains = &opl.GetAdlMetaIns(meta); int16_t tone = note; if(!isPercussion && !isXgPercussion && (bank > 0)) // For non-zero banks @@ -1072,23 +1074,18 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) { if(hooks.onDebugMessage) { - if(!caugh_missing_instruments.count(static_cast(midiins))) - { + if(caugh_missing_instruments.insert(static_cast(midiins)).second) hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Caugh a blank instrument %i (offset %i) in the MIDI bank %u", channel, Ch[channel].patch, midiins, bank); - caugh_missing_instruments.insert(static_cast(midiins)); - } } bank = 0; - midiins = Ch[channel].patch; - meta = opl.GetAdlMetaNumber(midiins); - ains = &opl.GetAdlMetaIns(meta); + midiins = midiChan.patch; } } if(ains->tone) { - /*if(ains.tone < 20) - tone += ains.tone; + /*if(ains->tone < 20) + tone += ains->tone; else*/ if(ains->tone < 128) tone = ains->tone; @@ -1096,30 +1093,38 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) tone -= ains->tone - 128; } - //uint16_t i[2] = { ains.adlno1, ains.adlno2 }; + //uint16_t i[2] = { ains->adlno1, ains->adlno2 }; bool pseudo_4op = ains->flags & adlinsdata::Flag_Pseudo4op; - MIDIchannel::NoteInfo::Phys voices[2] = +#ifndef __WATCOMC__ + MIDIchannel::NoteInfo::Phys voices[MIDIchannel::NoteInfo::MaxNumPhysChans] = { - {ains->adlno1, false}, - {ains->adlno2, pseudo_4op} + {0, ains->adl[0], false}, + {0, ains->adl[1], pseudo_4op} }; +#else /* Unfortunately, WatCom can't brace-initialize structure that incluses structure fields */ + MIDIchannel::NoteInfo::Phys voices[MIDIchannel::NoteInfo::MaxNumPhysChans]; + voices[0].chip_chan = 0; + voices[0].ains = ains->adl[0]; + voices[0].pseudo4op = false; + voices[1].chip_chan = 0; + voices[1].ains = ains->adl[1]; + voices[1].pseudo4op = pseudo_4op; +#endif /* __WATCOMC__ */ if((opl.AdlPercussionMode == 1) && PercussionMap[midiins & 0xFF]) voices[1] = voices[0];//i[1] = i[0]; if(hooks.onDebugMessage) { - if(!caugh_missing_instruments.count(static_cast(midiins)) && (ains->flags & adlinsdata::Flag_NoSound)) - { + if((ains->flags & adlinsdata::Flag_NoSound) && + caugh_missing_instruments.insert(static_cast(midiins)).second) hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing instrument %i", channel, midiins); - caugh_missing_instruments.insert(static_cast(midiins)); - } } // Allocate AdLib channel (the physical sound channel for the note) - int32_t adlchannel[2] = { -1, -1 }; + int32_t adlchannel[MIDIchannel::NoteInfo::MaxNumPhysChans] = { -1, -1 }; - for(uint32_t ccount = 0; ccount < 2; ++ccount) + for(uint32_t ccount = 0; ccount < MIDIchannel::NoteInfo::MaxNumPhysChans; ++ccount) { if(ccount == 1) { @@ -1137,7 +1142,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) if(ccount == 1 && static_cast(a) == adlchannel[0]) continue; // ^ Don't use the same channel for primary&secondary - if(voices[0].insId == voices[1].insId || pseudo_4op/*i[0] == i[1] || pseudo_4op*/) + if(voices[0].ains == voices[1].ains || pseudo_4op/*i[0] == i[1] || pseudo_4op*/) { // Only use regular channels uint8_t expected_mode = 0; @@ -1182,7 +1187,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) if(hooks.onDebugMessage) hooks.onDebugMessage(hooks.onDebugMessage_userData, "ignored unplaceable note [bank %i, inst %i, note %i, MIDI channel %i]", - bank, Ch[channel].patch, note, channel); + bank, midiChan.patch, note, channel); continue; // Could not play this note. Ignore it. } @@ -1201,19 +1206,21 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) // Allocate active note for MIDI channel std::pair - ir = Ch[channel].activenotes.insert(std::make_pair(note, MIDIchannel::NoteInfo())); - ir.first->second.vol = velocity; - ir.first->second.tone = tone; - ir.first->second.midiins = midiins; - ir.first->second.insmeta = meta; + ir = midiChan.activenotes_insert(note); + ir.first->vol = velocity; + ir.first->vibrato = midiChan.noteAftertouch[note]; + ir.first->tone = tone; + ir.first->midiins = midiins; + ir.first->ains = ains; + ir.first->chip_channels_count = 0; - for(unsigned ccount = 0; ccount < 2; ++ccount) + for(unsigned ccount = 0; ccount < MIDIchannel::NoteInfo::MaxNumPhysChans; ++ccount) { int32_t c = adlchannel[ccount]; if(c < 0) continue; uint16_t chipChan = static_cast(adlchannel[ccount]); - ir.first->second.phys[chipChan] = voices[ccount]; + ir.first->phys_ensure_find_or_create(chipChan)->assign(voices[ccount]); } NoteUpdate(channel, ir.first, Upd_All | Upd_Patch); return true; @@ -1228,31 +1235,28 @@ void MIDIplay::realTime_NoteOff(uint8_t channel, uint8_t note) void MIDIplay::realTime_NoteAfterTouch(uint8_t channel, uint8_t note, uint8_t atVal) { channel = channel % 16; - MIDIchannel::activenoteiterator - i = Ch[channel].activenotes.find(note); - if(i == Ch[channel].activenotes.end()) + MIDIchannel &chan = Ch[channel]; + MIDIchannel::activenoteiterator i = Ch[channel].activenotes_find(note); + if(i) { - // Ignore touch if note is not active - return; + i->vibrato = atVal; + } + + uint8_t oldAtVal = chan.noteAftertouch[note % 128]; + if(atVal != oldAtVal) + { + chan.noteAftertouch[note % 128] = atVal; + bool inUse = atVal != 0; + for(unsigned n = 0; !inUse && n < 128; ++n) + inUse = chan.noteAftertouch[n] != 0; + chan.noteAfterTouchInUse = inUse; } - i->second.vol = 127 - atVal; - NoteUpdate(channel, i, Upd_Volume); } void MIDIplay::realTime_ChannelAfterTouch(uint8_t channel, uint8_t atVal) { - // TODO: Verify, is this correct action? channel = channel % 16; - for(MIDIchannel::activenoteiterator - i = Ch[channel].activenotes.begin(); - i != Ch[channel].activenotes.end(); - ++i) - { - // Set this pressure to all active notes on the channel - i->second.vol = 127 - atVal; - } - - NoteUpdate_All(channel, Upd_Volume); + Ch[channel].aftertouch = atVal; } void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value) @@ -1312,30 +1316,24 @@ void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value) case 10: // Change panning Ch[channel].panning = 0x00; - if(value < 64 + 32) Ch[channel].panning |= 0x10; - if(value >= 64 - 32) Ch[channel].panning |= 0x20; + if(value < 64 + 32) Ch[channel].panning |= OPL_PANNING_LEFT; + if(value >= 64 - 32) Ch[channel].panning |= OPL_PANNING_RIGHT; NoteUpdate_All(channel, Upd_Pan); break; case 121: // Reset all controllers - Ch[channel].bend = 0; - Ch[channel].volume = 100; - Ch[channel].expression = 127; - Ch[channel].sustain = 0; - Ch[channel].vibrato = 0; - Ch[channel].vibspeed = 2 * 3.141592653 * 5.0; - Ch[channel].vibdepth = 0.5 / 127; - Ch[channel].vibdelay = 0; - Ch[channel].panning = 0x30; - Ch[channel].portamento = 0; - Ch[channel].brightness = 127; + Ch[channel].resetAllControllers(); //UpdatePortamento(MidCh); NoteUpdate_All(channel, Upd_Pan + Upd_Volume + Upd_Pitch); // Kill all sustained notes KillSustainingNotes(channel); break; + case 120: // All sounds off + NoteUpdate_All(channel, Upt_OffMute); + break; + case 123: // All notes off NoteUpdate_All(channel, Upd_Off); break; @@ -1405,14 +1403,14 @@ void MIDIplay::realTime_PatchChange(uint8_t channel, uint8_t patch) void MIDIplay::realTime_PitchBend(uint8_t channel, uint16_t pitch) { channel = channel % 16; - Ch[channel].bend = (uint32_t(pitch) - 8192) * Ch[channel].bendsense; + Ch[channel].bend = int(pitch) - 8192; NoteUpdate_All(channel, Upd_Pitch); } void MIDIplay::realTime_PitchBend(uint8_t channel, uint8_t msb, uint8_t lsb) { channel = channel % 16; - Ch[channel].bend = (int(lsb) + int(msb) * 128 - 8192) * Ch[channel].bendsense; + Ch[channel].bend = int(lsb) + int(msb) * 128 - 8192; NoteUpdate_All(channel, Upd_Pitch); } @@ -1441,85 +1439,97 @@ void MIDIplay::realTime_panic() KillSustainingNotes(-1, -1); } +void MIDIplay::AudioTick(uint32_t chipId, uint32_t /*rate*/) +{ + if(chipId != 0) // do first chip ticks only + return; + + /*uint32_t tickNumber = */m_audioTickCounter++; +} void MIDIplay::NoteUpdate(uint16_t MidCh, MIDIplay::MIDIchannel::activenoteiterator i, unsigned props_mask, int32_t select_adlchn) { - MIDIchannel::NoteInfo &info = i->second; + MIDIchannel::NoteInfo &info = *i; const int16_t tone = info.tone; const uint8_t vol = info.vol; - const int midiins = info.midiins; - const size_t insmeta = info.insmeta; - const adlinsdata &ains = opl.GetAdlMetaIns(insmeta); + const int midiins = static_cast(info.midiins); + const adlinsdata2 &ains = *info.ains; AdlChannel::Location my_loc; my_loc.MidCh = MidCh; - my_loc.note = i->first; + my_loc.note = info.note; - for(MIDIchannel::NoteInfo::PhysMap::iterator - jnext = info.phys.begin(); - jnext != info.phys.end(); - ) + for(unsigned ccount = 0, ctotal = info.chip_channels_count; ccount < ctotal; ccount++) { - MIDIchannel::NoteInfo::PhysMap::iterator j(jnext++); - uint16_t c = j->first; - const MIDIchannel::NoteInfo::Phys &ins = j->second; + const MIDIchannel::NoteInfo::Phys &ins = info.chip_channels[ccount]; + uint16_t c = ins.chip_chan; if(select_adlchn >= 0 && c != select_adlchn) continue; if(props_mask & Upd_Patch) { - opl.Patch(c, ins.insId); - AdlChannel::LocationData &d = ch[c].users[my_loc]; - d.sustained = false; // inserts if necessary - d.vibdelay = 0; - d.kon_time_until_neglible = ains.ms_sound_kon; - d.ins = ins; + opl.Patch(c, ins.ains); + AdlChannel::LocationData *d = ch[c].users_find_or_create(my_loc); + if(d) // inserts if necessary + { + d->sustained = false; + d->vibdelay = 0; + d->fixed_sustain = (ains.ms_sound_kon == static_cast(adlNoteOnMaxTime)); + d->kon_time_until_neglible = ains.ms_sound_kon; + d->ins = ins; + } } } - for(MIDIchannel::NoteInfo::PhysMap::iterator - jnext = info.phys.begin(); - jnext != info.phys.end(); - ) + for(unsigned ccount = 0; ccount < info.chip_channels_count; ccount++) { - MIDIchannel::NoteInfo::PhysMap::iterator j(jnext++); - uint16_t c = j->first; - const MIDIchannel::NoteInfo::Phys &ins = j->second; + const MIDIchannel::NoteInfo::Phys &ins = info.chip_channels[ccount]; + uint16_t c = ins.chip_chan; - if(select_adlchn >= 0 && c != select_adlchn) continue; + if(select_adlchn >= 0 && c != select_adlchn) + continue; if(props_mask & Upd_Off) // note off { if(Ch[MidCh].sustain == 0) { - AdlChannel::users_t::iterator k = ch[c].users.find(my_loc); + AdlChannel::LocationData *k = ch[c].users_find(my_loc); - if(k != ch[c].users.end()) - ch[c].users.erase(k); + if(k) + ch[c].users_erase(k); if(hooks.onNote) hooks.onNote(hooks.onNote_userData, c, tone, midiins, 0, 0.0); - if(ch[c].users.empty()) + if(ch[c].users_empty()) { opl.NoteOff(c); - ch[c].koff_time_until_neglible = - ains.ms_sound_koff; + if(props_mask & Upd_Mute) // Mute the note + { + opl.Touch_Real(c, 0); + ch[c].koff_time_until_neglible = 0; + } + else + { + ch[c].koff_time_until_neglible = ains.ms_sound_koff; + } } } else { // Sustain: Forget about the note, but don't key it off. // Also will avoid overwriting it very soon. - AdlChannel::LocationData &d = ch[c].users[my_loc]; - d.sustained = true; // note: not erased! + AdlChannel::LocationData *d = ch[c].users_find_or_create(my_loc); + if(d) + d->sustained = true; // note: not erased! if(hooks.onNote) hooks.onNote(hooks.onNote_userData, c, tone, midiins, -1, 0.0); } - info.phys.erase(j); + info.phys_erase_at(&ins); // decrements channel count + --ccount; // adjusts index accordingly continue; } @@ -1532,10 +1542,19 @@ void MIDIplay::NoteUpdate(uint16_t MidCh, bool is_percussion = (MidCh == 9) || Ch[MidCh].is_xg_percussion; uint8_t brightness = is_percussion ? 127 : Ch[MidCh].brightness; + if(!m_setup.fullRangeBrightnessCC74) + { + // Simulate post-High-Pass filter result which affects sounding by half level only + if(brightness >= 64) + brightness = 127; + else + brightness *= 2; + } + switch(opl.m_volumeScale) { + case OPL3::VOLUME_Generic: - case OPL3::VOLUME_CMF: { volume = vol * Ch[MidCh].volume * Ch[MidCh].expression; @@ -1548,25 +1567,29 @@ void MIDIplay::NoteUpdate(uint16_t MidCh, */ //volume = (int)(volume * std::sqrt( (double) ch[c].users.size() )); - if(opl.LogarithmicVolumes) - volume = volume * 127 / (127 * 127 * 127) / 2; - else - { - // The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A) - volume = volume > 8725 ? static_cast(std::log(static_cast(volume)) * 11.541561 + (0.5 - 104.22845)) : 0; - // The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A) - //opl.Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0); - } + // The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A) + volume = volume > 8725 ? static_cast(std::log(static_cast(volume)) * 11.541561 + (0.5 - 104.22845)) : 0; + // The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A) + //opl.Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0); + opl.Touch_Real(c, volume, brightness); //opl.Touch(c, volume); } break; + case OPL3::VOLUME_NATIVE: + { + volume = vol * Ch[MidCh].volume * Ch[MidCh].expression; + volume = volume * 127 / (127 * 127 * 127) / 2; + opl.Touch_Real(c, volume, brightness); + } + break; + case OPL3::VOLUME_DMX: { volume = 2 * ((Ch[MidCh].volume * Ch[MidCh].expression) * 127 / 16129) + 1; //volume = 2 * (Ch[MidCh].volume) + 1; - volume = (DMX_volume_mapping_table[vol] * volume) >> 9; + volume = (DMX_volume_mapping_table[(vol < 128) ? vol : 127] * volume) >> 9; opl.Touch_Real(c, volume, brightness); } break; @@ -1606,37 +1629,40 @@ void MIDIplay::NoteUpdate(uint16_t MidCh, if(props_mask & Upd_Pitch) { - AdlChannel::LocationData &d = ch[c].users[my_loc]; + AdlChannel::LocationData *d = ch[c].users_find(my_loc); // Don't bend a sustained note - if(!d.sustained) + if(!d || !d->sustained) { - double bend = Ch[MidCh].bend + opl.GetAdlIns(ins.insId).finetune; + double midibend = Ch[MidCh].bend * Ch[MidCh].bendsense; + double bend = midibend + ins.ains.finetune; double phase = 0.0; + uint8_t vibrato = std::max(Ch[MidCh].vibrato, Ch[MidCh].aftertouch); + vibrato = std::max(vibrato, i->vibrato); if((ains.flags & adlinsdata::Flag_Pseudo4op) && ins.pseudo4op) { phase = ains.voice2_fine_tune;//0.125; // Detune the note slightly (this is what Doom does) } - if(Ch[MidCh].vibrato && d.vibdelay >= Ch[MidCh].vibdelay) - bend += Ch[MidCh].vibrato * Ch[MidCh].vibdepth * std::sin(Ch[MidCh].vibpos); + if(vibrato && (!d || d->vibdelay >= Ch[MidCh].vibdelay)) + bend += static_cast(vibrato) * Ch[MidCh].vibdepth * std::sin(Ch[MidCh].vibpos); - #ifdef ADLMIDI_USE_DOSBOX_OPL -#define BEND_COEFFICIENT 172.00093 - #else -#define BEND_COEFFICIENT 172.4387 - #endif - opl.NoteOn(c, BEND_COEFFICIENT * std::exp(0.057762265 * (tone + bend + phase))); +#ifdef ADLMIDI_USE_DOSBOX_OPL +# define BEND_COEFFICIENT 172.00093 +#else +# define BEND_COEFFICIENT 172.4387 +#endif + opl.NoteOn(c, BEND_COEFFICIENT * std::exp(0.057762265 * (static_cast(tone) + bend + phase))); #undef BEND_COEFFICIENT if(hooks.onNote) - hooks.onNote(hooks.onNote_userData, c, tone, midiins, vol, Ch[MidCh].bend); + hooks.onNote(hooks.onNote_userData, c, tone, midiins, vol, midibend); } } } - if(info.phys.empty()) - Ch[MidCh].activenotes.erase(i); + if(info.chip_channels_count == 0) + Ch[MidCh].activenotes_erase(i); } #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER @@ -1651,9 +1677,9 @@ bool MIDIplay::ProcessEventsNew(bool isSeek) const size_t TrackCount = CurrentPositionNew.track.size(); const PositionNew RowBeginPosition(CurrentPositionNew); - #ifdef DEBUG_TIME_CALCULATION +#ifdef DEBUG_TIME_CALCULATION double maxTime = 0.0; - #endif +#endif for(size_t tk = 0; tk < TrackCount; ++tk) { @@ -1671,10 +1697,10 @@ bool MIDIplay::ProcessEventsNew(bool isSeek) for(size_t i = 0; i < track.pos->events.size(); i++) { const MidiEvent &evt = track.pos->events[i]; - #ifdef ENABLE_BEGIN_SILENCE_SKIPPING +#ifdef ENABLE_BEGIN_SILENCE_SKIPPING if(!CurrentPositionNew.began && (evt.type == MidiEvent::T_NOTEON)) CurrentPositionNew.began = true; - #endif +#endif if(isSeek && (evt.type == MidiEvent::T_NOTEON)) continue; HandleEvent(tk, evt, track.status); @@ -1682,10 +1708,10 @@ bool MIDIplay::ProcessEventsNew(bool isSeek) break;//Stop event handling on catching loopEnd event! } - #ifdef DEBUG_TIME_CALCULATION +#ifdef DEBUG_TIME_CALCULATION if(maxTime < track.pos->time) maxTime = track.pos->time; - #endif +#endif // Read next event time (unless the track just ended) if(track.status >= 0) { @@ -1695,11 +1721,11 @@ bool MIDIplay::ProcessEventsNew(bool isSeek) } } - #ifdef DEBUG_TIME_CALCULATION +#ifdef DEBUG_TIME_CALCULATION std::fprintf(stdout, " \r"); std::fprintf(stdout, "Time: %10f; Audio: %10f\r", maxTime, CurrentPositionNew.absTimePosition); std::fflush(stdout); - #endif +#endif // Find shortest delay from all track uint64_t shortest = 0; @@ -1723,9 +1749,9 @@ bool MIDIplay::ProcessEventsNew(bool isSeek) fraction t = shortest * Tempo; - #ifdef ENABLE_BEGIN_SILENCE_SKIPPING +#ifdef ENABLE_BEGIN_SILENCE_SKIPPING if(CurrentPositionNew.began) - #endif +#endif CurrentPositionNew.wait += t.value(); //if(shortest > 0) UI.PrintLn("Delay %ld (%g)", shortest, (double)t.valuel()); @@ -1751,9 +1777,7 @@ bool MIDIplay::ProcessEventsNew(bool isSeek) return true;//Has events in queue } -#endif -#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t **pptr, uint8_t *end, int &status) { uint8_t *&ptr = *pptr; @@ -1801,6 +1825,14 @@ MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t **pptr, uint8_t *end, int &stat evt.subtype = evtype; evt.data.insert(evt.data.begin(), data.begin(), data.end()); +#if 0 /* Print all tempo events */ + if(evt.subtype == MidiEvent::ST_TEMPOCHANGE) + { + if(hooks.onDebugMessage) + hooks.onDebugMessage(hooks.onDebugMessage_userData, "Temp Change: %02X%02X%02X", evt.data[0], evt.data[1], evt.data[2]); + } +#endif + /* TODO: Store those meta-strings separately and give ability to read them * by external functions (to display song title and copyright in the player) */ if(evt.subtype == MidiEvent::ST_COPYRIGHT) @@ -1931,9 +1963,16 @@ MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t **pptr, uint8_t *end, int &stat evt.data.push_back(*(ptr++)); evt.data.push_back(*(ptr++)); - if((evType == MidiEvent::T_NOTEON) && (evt.data[1] == 0)) + /* TODO: Implement conversion of RSXX's note volumes out of synthesizer */ + /*if((opl.m_musicMode == OPL3::MODE_RSXX) && (evType == MidiEvent::T_NOTEON) && (evt.data[1] != 0)) + { + //NOT WORKING YET + evt.type = MidiEvent::T_NOTETOUCH; + } + else */if((evType == MidiEvent::T_NOTEON) && (evt.data[1] == 0)) + { evt.type = MidiEvent::T_NOTEOFF; // Note ON with zero velocity is Note OFF! - //111'th loopStart controller (RPG Maker and others) + } //111'th loopStart controller (RPG Maker and others) else if((evType == MidiEvent::T_CTRLCHANGE) && (evt.data[0] == 111)) { //Change event type to custom Loop Start event and clear data @@ -1957,7 +1996,7 @@ MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t **pptr, uint8_t *end, int &stat return evt; } -#endif +#endif /* ADLMIDI_DISABLE_MIDI_SEQUENCER */ const std::string &MIDIplay::getErrorString() { @@ -2046,7 +2085,7 @@ void MIDIplay::HandleEvent(size_t tk, const MIDIplay::MidiEvent &evt, int &statu v |= 0x30; //std::printf("OPL poke %02X, %02X\n", i, v); //std::fflush(stdout); - opl.PokeN(0, i, v); + opl.Poke(0, i, v); return; } @@ -2126,43 +2165,40 @@ void MIDIplay::HandleEvent(size_t tk, const MIDIplay::MidiEvent &evt, int &statu } } } -#endif +#endif /* ADLMIDI_DISABLE_MIDI_SEQUENCER */ -int64_t MIDIplay::CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t) const +int64_t MIDIplay::CalculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t) const { int64_t s = -ch[c].koff_time_until_neglible; // Same midi-instrument = some stability //if(c == MidCh) s += 4; - for(AdlChannel::users_t::const_iterator - j = ch[c].users.begin(); - j != ch[c].users.end(); - ++j) + for(AdlChannel::LocationData *j = ch[c].users_first; j; j = j->next) { s -= 4000; - if(!j->second.sustained) - s -= j->second.kon_time_until_neglible; + if(!j->sustained) + s -= j->kon_time_until_neglible; else - s -= (j->second.kon_time_until_neglible / 2); + s -= (j->kon_time_until_neglible / 2); - MIDIchannel::activenotemap_t::const_iterator - k = Ch[j->first.MidCh].activenotes.find(j->first.note); + MIDIchannel::activenoteiterator + k = const_cast(Ch[j->loc.MidCh]).activenotes_find(j->loc.note); - if(k != Ch[j->first.MidCh].activenotes.end()) + if(k) { // Same instrument = good - if(j->second.ins == ins) + if(j->ins == ins) { s += 300; // Arpeggio candidate = even better - if(j->second.vibdelay < 70 - || j->second.kon_time_until_neglible > 20000) + if(j->vibdelay < 70 + || j->kon_time_until_neglible > 20000) s += 0; } // Percussion is inferior to melody - s += 50 * (int64_t)(k->second.midiins / 128); + s += 50 * (int64_t)(k->midiins / 128); /* if(k->second.midiins >= 25 && k->second.midiins < 40 @@ -2178,21 +2214,18 @@ int64_t MIDIplay::CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::Not // increase the score slightly. unsigned n_evacuation_stations = 0; - for(unsigned c2 = 0; c2 < opl.NumChannels; ++c2) + for(size_t c2 = 0; c2 < static_cast(opl.NumChannels); ++c2) { if(c2 == c) continue; if(opl.four_op_category[c2] != opl.four_op_category[c]) continue; - for(AdlChannel::users_t::const_iterator - m = ch[c2].users.begin(); - m != ch[c2].users.end(); - ++m) + for(AdlChannel::LocationData *m = ch[c2].users_first; m; m = m->next) { - if(m->second.sustained) continue; - if(m->second.vibdelay >= 200) continue; - if(m->second.ins != j->second.ins) continue; + if(m->sustained) continue; + if(m->vibdelay >= 200) continue; + if(m->ins != j->ins) continue; n_evacuation_stations += 1; } } @@ -2206,27 +2239,25 @@ int64_t MIDIplay::CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::Not void MIDIplay::PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins) { - if(ch[c].users.empty()) return; // Nothing to do + if(ch[c].users_empty()) return; // Nothing to do //bool doing_arpeggio = false; - for(AdlChannel::users_t::iterator - jnext = ch[c].users.begin(); - jnext != ch[c].users.end(); - ) + for(AdlChannel::LocationData *jnext = ch[c].users_first; jnext;) { - AdlChannel::users_t::iterator j(jnext++); + AdlChannel::LocationData *j = jnext; + jnext = jnext->next; - if(!j->second.sustained) + if(!j->sustained) { // Collision: Kill old note, // UNLESS we're going to do arpeggio MIDIchannel::activenoteiterator i - (Ch[j->first.MidCh].activenotes.find(j->first.note)); + (Ch[j->loc.MidCh].activenotes_ensure_find(j->loc.note)); // Check if we can do arpeggio. - if((j->second.vibdelay < 70 - || j->second.kon_time_until_neglible > 20000) - && j->second.ins == ins) + if((j->vibdelay < 70 + || j->kon_time_until_neglible > 20000) + && j->ins == ins) { // Do arpeggio together with this note. //doing_arpeggio = true; @@ -2245,11 +2276,13 @@ void MIDIplay::PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo // Keyoff the channel so that it can be retriggered, // unless the new note will be introduced as just an arpeggio. - if(ch[c].users.empty()) + if(ch[c].users_empty()) opl.NoteOff(c); } -void MIDIplay::KillOrEvacuate(size_t from_channel, AdlChannel::users_t::iterator j, MIDIplay::MIDIchannel::activenoteiterator i) +void MIDIplay::KillOrEvacuate(size_t from_channel, + AdlChannel::LocationData *j, + MIDIplay::MIDIchannel::activenoteiterator i) { // Before killing the note, check if it can be // evacuated to another channel as an arpeggio @@ -2267,32 +2300,34 @@ void MIDIplay::KillOrEvacuate(size_t from_channel, AdlChannel::users_t::iterator if(opl.four_op_category[c] != opl.four_op_category[from_channel]) continue; - for(AdlChannel::users_t::iterator - m = ch[c].users.begin(); - m != ch[c].users.end(); - ++m) + AdlChannel &adlch = ch[c]; + if(adlch.users_size == AdlChannel::users_max) + continue; // no room for more arpeggio on channel + + for(AdlChannel::LocationData *m = adlch.users_first; m; m = m->next) { - if(m->second.vibdelay >= 200 - && m->second.kon_time_until_neglible < 10000) continue; - if(m->second.ins != j->second.ins) + if(m->vibdelay >= 200 + && m->kon_time_until_neglible < 10000) continue; + if(m->ins != j->ins) continue; if(hooks.onNote) { hooks.onNote(hooks.onNote_userData, (int)from_channel, - i->second.tone, - i->second.midiins, 0, 0.0); + i->tone, + static_cast(i->midiins), 0, 0.0); hooks.onNote(hooks.onNote_userData, (int)c, - i->second.tone, - i->second.midiins, - i->second.vol, 0.0); + i->tone, + static_cast(i->midiins), + i->vol, 0.0); } - i->second.phys.erase(static_cast(from_channel)); - i->second.phys[cs] = j->second.ins; - ch[cs].users.insert(*j); - ch[from_channel].users.erase(j); + i->phys_erase(static_cast(from_channel)); + i->phys_ensure_find_or_create(cs)->assign(j->ins); + if(!ch[cs].users_insert(*j)) + assert(false); + ch[from_channel].users_erase(j); return; } } @@ -2305,7 +2340,7 @@ void MIDIplay::KillOrEvacuate(size_t from_channel, AdlChannel::users_t::iterator ins );*/ // Kill it - NoteUpdate(j->first.MidCh, + NoteUpdate(j->loc.MidCh, i, Upd_Off, static_cast(from_channel)); @@ -2332,27 +2367,25 @@ void MIDIplay::KillSustainingNotes(int32_t MidCh, int32_t this_adlchn) for(unsigned c = first; c < last; ++c) { - if(ch[c].users.empty()) continue; // Nothing to do + if(ch[c].users_empty()) continue; // Nothing to do - for(AdlChannel::users_t::iterator - jnext = ch[c].users.begin(); - jnext != ch[c].users.end(); - ) + for(AdlChannel::LocationData *jnext = ch[c].users_first; jnext;) { - AdlChannel::users_t::iterator j(jnext++); + AdlChannel::LocationData *j = jnext; + jnext = jnext->next; - if((MidCh < 0 || j->first.MidCh == MidCh) - && j->second.sustained) + if((MidCh < 0 || j->loc.MidCh == MidCh) + && j->sustained) { int midiins = '?'; if(hooks.onNote) - hooks.onNote(hooks.onNote_userData, (int)c, j->first.note, midiins, 0, 0.0); - ch[c].users.erase(j); + hooks.onNote(hooks.onNote_userData, (int)c, j->loc.note, midiins, 0, 0.0); + ch[c].users_erase(j); } } // Keyoff the channel, if there are no users left. - if(ch[c].users.empty()) + if(ch[c].users_empty()) opl.NoteOff(c); } } @@ -2365,7 +2398,12 @@ void MIDIplay::SetRPN(unsigned MidCh, unsigned value, bool MSB) switch(addr + nrpn * 0x10000 + MSB * 0x20000) { case 0x0000 + 0*0x10000 + 1*0x20000: // Pitch-bender sensitivity - Ch[MidCh].bendsense = value / 8192.0; + Ch[MidCh].bendsense_msb = value; + Ch[MidCh].updateBendSensitivity(); + break; + case 0x0000 + 0*0x10000 + 0*0x20000: // Pitch-bender sensitivity LSB + Ch[MidCh].bendsense_lsb = value; + Ch[MidCh].updateBendSensitivity(); break; case 0x0108 + 1*0x10000 + 1*0x20000: // Vibrato speed if(value == 64) Ch[MidCh].vibspeed = 1.0; @@ -2398,9 +2436,7 @@ void MIDIplay::SetRPN(unsigned MidCh, unsigned value, bool MSB) void MIDIplay::NoteUpdate_All(uint16_t MidCh, unsigned props_mask) { for(MIDIchannel::activenoteiterator - i = Ch[MidCh].activenotes.begin(); - i != Ch[MidCh].activenotes.end(); - ) + i = Ch[MidCh].activenotes_begin(); i;) { MIDIchannel::activenoteiterator j(i++); NoteUpdate(MidCh, j, props_mask); @@ -2410,9 +2446,9 @@ void MIDIplay::NoteUpdate_All(uint16_t MidCh, unsigned props_mask) void MIDIplay::NoteOff(uint16_t MidCh, uint8_t note) { MIDIchannel::activenoteiterator - i = Ch[MidCh].activenotes.find(note); + i = Ch[MidCh].activenotes_find(note); - if(i != Ch[MidCh].activenotes.end()) + if(i) NoteUpdate(MidCh, i, Upd_Off); } @@ -2421,7 +2457,7 @@ void MIDIplay::UpdateVibrato(double amount) { for(size_t a = 0, b = Ch.size(); a < b; ++a) { - if(Ch[a].vibrato && !Ch[a].activenotes.empty()) + if(Ch[a].hasVibrato() && !Ch[a].activenotes_empty()) { NoteUpdate_All(static_cast(a), Upd_Pitch); Ch[a].vibpos += amount * Ch[a].vibspeed; @@ -2451,9 +2487,9 @@ void MIDIplay::UpdateArpeggio(double) // amount = amount of time passed { // If there is an adlib channel that has multiple notes // simulated on the same channel, arpeggio them. - #if 0 +#if 0 const unsigned desired_arpeggio_rate = 40; // Hz (upper limit) - #if 1 +# if 1 static unsigned cache = 0; amount = amount; // Ignore amount. Assume we get a constant rate. cache += MaxSamplesAtTime * desired_arpeggio_rate; @@ -2461,17 +2497,17 @@ void MIDIplay::UpdateArpeggio(double) // amount = amount of time passed if(cache < PCM_RATE) return; cache %= PCM_RATE; - #else +# else static double arpeggio_cache = 0; arpeggio_cache += amount * desired_arpeggio_rate; if(arpeggio_cache < 1.0) return; arpeggio_cache = 0.0; - #endif - #endif - static unsigned arpeggio_counter = 0; - ++arpeggio_counter; +# endif +#endif + + ++m_arpeggioCounter; for(uint32_t c = 0; c < opl.NumChannels; ++c) { @@ -2479,11 +2515,11 @@ retry_arpeggio: if(c > uint32_t(std::numeric_limits::max())) break; - size_t n_users = ch[c].users.size(); + size_t n_users = ch[c].users_size; if(n_users > 1) { - AdlChannel::users_t::const_iterator i = ch[c].users.begin(); + AdlChannel::LocationData *i = ch[c].users_first; size_t rate_reduction = 3; if(n_users >= 3) @@ -2492,23 +2528,25 @@ retry_arpeggio: if(n_users >= 4) rate_reduction = 1; - std::advance(i, (arpeggio_counter / rate_reduction) % n_users); + for(size_t count = (m_arpeggioCounter / rate_reduction) % n_users, + n = 0; n < count; ++n) + i = i->next; - if(i->second.sustained == false) + if(i->sustained == false) { - if(i->second.kon_time_until_neglible <= 0l) + if(i->kon_time_until_neglible <= 0l) { NoteUpdate( - i->first.MidCh, - Ch[ i->first.MidCh ].activenotes.find(i->first.note), + i->loc.MidCh, + Ch[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note), Upd_Off, static_cast(c)); goto retry_arpeggio; } NoteUpdate( - i->first.MidCh, - Ch[ i->first.MidCh ].activenotes.find(i->first.note), + i->loc.MidCh, + Ch[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note), Upd_Pitch | Upd_Volume | Upd_Pan, static_cast(c)); } @@ -2519,36 +2557,48 @@ retry_arpeggio: #ifndef ADLMIDI_DISABLE_CPP_EXTRAS -ADLMIDI_EXPORT AdlInstrumentTester::AdlInstrumentTester(ADL_MIDIPlayer *device) +struct AdlInstrumentTester::Impl { - cur_gm = 0; - ins_idx = 0; - play = reinterpret_cast(device->adl_midiPlayer); - if(!play) - return; - opl = &play->opl; + uint32_t cur_gm; + uint32_t ins_idx; + std::vector adl_ins_list; + OPL3 *opl; + MIDIplay *play; +}; + +ADLMIDI_EXPORT AdlInstrumentTester::AdlInstrumentTester(ADL_MIDIPlayer *device) + : P(new Impl) +{ + MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); + P->cur_gm = 0; + P->ins_idx = 0; + P->play = play; + P->opl = play ? &play->opl : NULL; } ADLMIDI_EXPORT AdlInstrumentTester::~AdlInstrumentTester() -{} +{ + delete P; +} ADLMIDI_EXPORT void AdlInstrumentTester::FindAdlList() { const unsigned NumBanks = (unsigned)adl_getBanksCount(); std::set adl_ins_set; for(unsigned bankno = 0; bankno < NumBanks; ++bankno) - adl_ins_set.insert(banks[bankno][cur_gm]); - adl_ins_list.assign(adl_ins_set.begin(), adl_ins_set.end()); - ins_idx = 0; + adl_ins_set.insert(banks[bankno][P->cur_gm]); + P->adl_ins_list.assign(adl_ins_set.begin(), adl_ins_set.end()); + P->ins_idx = 0; NextAdl(0); - opl->Silence(); + P->opl->Silence(); } ADLMIDI_EXPORT void AdlInstrumentTester::Touch(unsigned c, unsigned volume) // Volume maxes at 127*127*127 { - if(opl->LogarithmicVolumes) + OPL3 *opl = P->opl; + if(opl->m_volumeScale == OPL3::VOLUME_NATIVE) opl->Touch_Real(c, volume * 127 / (127 * 127 * 127) / 2); else { @@ -2561,11 +2611,13 @@ ADLMIDI_EXPORT void AdlInstrumentTester::Touch(unsigned c, unsigned volume) // V ADLMIDI_EXPORT void AdlInstrumentTester::DoNote(int note) { - if(adl_ins_list.empty()) FindAdlList(); - const unsigned meta = adl_ins_list[ins_idx]; - const adlinsdata &ains = opl->GetAdlMetaIns(meta); + MIDIplay *play = P->play; + OPL3 *opl = P->opl; + if(P->adl_ins_list.empty()) FindAdlList(); + const unsigned meta = P->adl_ins_list[P->ins_idx]; + const adlinsdata2 ains(adlins[meta]); - int tone = (cur_gm & 128) ? (cur_gm & 127) : (note + 50); + int tone = (P->cur_gm & 128) ? (P->cur_gm & 127) : (note + 50); if(ains.tone) { /*if(ains.tone < 20) @@ -2577,16 +2629,15 @@ ADLMIDI_EXPORT void AdlInstrumentTester::DoNote(int note) tone -= ains.tone - 128; } double hertz = 172.00093 * std::exp(0.057762265 * (tone + 0.0)); - int i[2] = { ains.adlno1, ains.adlno2 }; int32_t adlchannel[2] = { 0, 3 }; - if(i[0] == i[1]) + if(ains.adl[0] == ains.adl[1]) { adlchannel[1] = -1; adlchannel[0] = 6; // single-op if(play->hooks.onDebugMessage) { play->hooks.onDebugMessage(play->hooks.onDebugMessage_userData, - "noteon at %d(%d) for %g Hz\n", adlchannel[0], i[0], hertz); + "noteon at %d for %g Hz\n", adlchannel[0], hertz); } } else @@ -2594,7 +2645,7 @@ ADLMIDI_EXPORT void AdlInstrumentTester::DoNote(int note) if(play->hooks.onDebugMessage) { play->hooks.onDebugMessage(play->hooks.onDebugMessage_userData, - "noteon at %d(%d) and %d(%d) for %g Hz\n", adlchannel[0], i[0], adlchannel[1], i[1], hertz); + "noteon at %d and %d for %g Hz\n", adlchannel[0], adlchannel[1], hertz); } } @@ -2604,7 +2655,7 @@ ADLMIDI_EXPORT void AdlInstrumentTester::DoNote(int note) for(unsigned c = 0; c < 2; ++c) { if(adlchannel[c] < 0) continue; - opl->Patch((uint16_t)adlchannel[c], (uint16_t)i[c]); + opl->Patch((uint16_t)adlchannel[c], ains.adl[c]); opl->Touch_Real((uint16_t)adlchannel[c], 127 * 127 * 100); opl->Pan((uint16_t)adlchannel[c], 0x30); opl->NoteOn((uint16_t)adlchannel[c], hertz); @@ -2613,17 +2664,18 @@ ADLMIDI_EXPORT void AdlInstrumentTester::DoNote(int note) ADLMIDI_EXPORT void AdlInstrumentTester::NextGM(int offset) { - cur_gm = (cur_gm + 256 + (uint32_t)offset) & 0xFF; + P->cur_gm = (P->cur_gm + 256 + (uint32_t)offset) & 0xFF; FindAdlList(); } ADLMIDI_EXPORT void AdlInstrumentTester::NextAdl(int offset) { - if(adl_ins_list.empty()) FindAdlList(); + //OPL3 *opl = P->opl; + if(P->adl_ins_list.empty()) FindAdlList(); const unsigned NumBanks = (unsigned)adl_getBanksCount(); - ins_idx = (uint32_t)((int32_t)ins_idx + (int32_t)adl_ins_list.size() + offset) % adl_ins_list.size(); + P->ins_idx = (uint32_t)((int32_t)P->ins_idx + (int32_t)P->adl_ins_list.size() + offset) % P->adl_ins_list.size(); - #if 0 +#if 0 UI.Color(15); std::fflush(stderr); std::printf("SELECTED G%c%d\t%s\n", @@ -2632,12 +2684,12 @@ ADLMIDI_EXPORT void AdlInstrumentTester::NextAdl(int offset) std::fflush(stdout); UI.Color(7); std::fflush(stderr); - #endif +#endif - for(unsigned a = 0; a < adl_ins_list.size(); ++a) + for(unsigned a = 0, n = P->adl_ins_list.size(); a < n; ++a) { - const unsigned i = adl_ins_list[a]; - const adlinsdata &ains = opl->GetAdlMetaIns(i); + const unsigned i = P->adl_ins_list[a]; + const adlinsdata2 ains(adlins[i]); char ToneIndication[8] = " "; if(ains.tone) @@ -2652,13 +2704,13 @@ ADLMIDI_EXPORT void AdlInstrumentTester::NextAdl(int offset) } std::printf("%s%s%s%u\t", ToneIndication, - ains.adlno1 != ains.adlno2 ? "[2]" : " ", - (ins_idx == a) ? "->" : "\t", + ains.adl[0] != ains.adl[1] ? "[2]" : " ", + (P->ins_idx == a) ? "->" : "\t", i ); for(unsigned bankno = 0; bankno < NumBanks; ++bankno) - if(banks[bankno][cur_gm] == i) + if(banks[bankno][P->cur_gm] == i) std::printf(" %u", bankno); std::printf("\n"); @@ -2692,9 +2744,9 @@ ADLMIDI_EXPORT bool AdlInstrumentTester::HandleInputChar(char ch) NextGM(+1); break; case 3: - #if !((!defined(__WIN32__) || defined(__CYGWIN__)) && !defined(__DJGPP__)) +#if !((!defined(__WIN32__) || defined(__CYGWIN__)) && !defined(__DJGPP__)) case 27: - #endif +#endif return false; default: const char *p = std::strchr(notes, ch); @@ -2704,4 +2756,130 @@ ADLMIDI_EXPORT bool AdlInstrumentTester::HandleInputChar(char ch) return true; } -#endif//ADLMIDI_DISABLE_CPP_EXTRAS +#endif /* ADLMIDI_DISABLE_CPP_EXTRAS */ + +// Implement the user map data structure. + +bool MIDIplay::AdlChannel::users_empty() const +{ + return !users_first; +} + +MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_find(Location loc) +{ + LocationData *user = NULL; + for(LocationData *curr = users_first; !user && curr; curr = curr->next) + if(curr->loc == loc) + user = curr; + return user; +} + +MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_allocate() +{ + // remove free cells front + LocationData *user = users_free_cells; + if(!user) + return NULL; + users_free_cells = user->next; + if(users_free_cells) + users_free_cells->prev = NULL; + // add to users front + if(users_first) + users_first->prev = user; + user->prev = NULL; + user->next = users_first; + users_first = user; + ++users_size; + return user; +} + +MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_find_or_create(Location loc) +{ + LocationData *user = users_find(loc); + if(!user) + { + user = users_allocate(); + if(!user) + return NULL; + LocationData *prev = user->prev, *next = user->next; + *user = LocationData(); + user->prev = prev; + user->next = next; + user->loc = loc; + } + return user; +} + +MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_insert(const LocationData &x) +{ + LocationData *user = users_find(x.loc); + if(!user) + { + user = users_allocate(); + if(!user) + return NULL; + LocationData *prev = user->prev, *next = user->next; + *user = x; + user->prev = prev; + user->next = next; + } + return user; +} + +void MIDIplay::AdlChannel::users_erase(LocationData *user) +{ + if(user->prev) + user->prev->next = user->next; + if(user->next) + user->next->prev = user->prev; + if(user == users_first) + users_first = user->next; + user->prev = NULL; + user->next = users_free_cells; + users_free_cells = user; + --users_size; +} + +void MIDIplay::AdlChannel::users_clear() +{ + users_first = NULL; + users_free_cells = users_cells; + users_size = 0; + for(size_t i = 0; i < users_max; ++i) + { + users_cells[i].prev = (i > 0) ? &users_cells[i - 1] : NULL; + users_cells[i].next = (i + 1 < users_max) ? &users_cells[i + 1] : NULL; + } +} + +void MIDIplay::AdlChannel::users_assign(const LocationData *users, size_t count) +{ + ADL_UNUSED(count);//Avoid warning for release builds + assert(count <= users_max); + if(users == users_first && users) + { + // self assignment + assert(users_size == count); + return; + } + users_clear(); + const LocationData *src_cell = users; + // move to the last + if(src_cell) + { + while(src_cell->next) + src_cell = src_cell->next; + } + // push cell copies in reverse order + while(src_cell) + { + LocationData *dst_cell = users_allocate(); + assert(dst_cell); + LocationData *prev = dst_cell->prev, *next = dst_cell->next; + *dst_cell = *src_cell; + dst_cell->prev = prev; + dst_cell->next = next; + src_cell = src_cell->prev; + } + assert(users_size == count); +} diff --git a/src/sound/adlmidi/adlmidi_opl3.cpp b/src/sound/adlmidi/adlmidi_opl3.cpp index 7ac8f309a..49e2e76c5 100644 --- a/src/sound/adlmidi/adlmidi_opl3.cpp +++ b/src/sound/adlmidi/adlmidi_opl3.cpp @@ -25,6 +25,21 @@ #ifdef ADLMIDI_HW_OPL static const unsigned OPLBase = 0x388; +#else +# if defined(ADLMIDI_DISABLE_NUKED_EMULATOR) && defined(ADLMIDI_DISABLE_DOSBOX_EMULATOR) +# error "No emulators enabled. You must enable at least one emulator to use this library!" +# endif + +// Nuked OPL3 emulator, Most accurate, but requires the powerful CPU +# ifndef ADLMIDI_DISABLE_NUKED_EMULATOR +# include "chips/nuked_opl3.h" +# include "chips/nuked_opl3_v174.h" +# endif + +// DosBox 0.74 OPL3 emulator, Well-accurate and fast +# ifndef ADLMIDI_DISABLE_DOSBOX_EMULATOR +# include "chips/dosbox_opl3.h" +# endif #endif #ifdef DISABLE_EMBEDDED_BANKS @@ -114,87 +129,56 @@ static const unsigned short Channels[23] = Ports: ??? */ - -const adlinsdata &OPL3::GetAdlMetaIns(size_t n) -{ - return (n & DynamicMetaInstrumentTag) ? - dynamic_metainstruments[n & ~DynamicMetaInstrumentTag] - : adlins[n]; -} - -size_t OPL3::GetAdlMetaNumber(size_t midiins) -{ - return (AdlBank == ~0u) ? - (midiins | DynamicMetaInstrumentTag) - : banks[AdlBank][midiins]; -} - -const adldata &OPL3::GetAdlIns(size_t insno) -{ - return (insno & DynamicInstrumentTag) - ? dynamic_instruments[insno & ~DynamicInstrumentTag] - : adl[insno]; -} - void OPL3::setEmbeddedBank(unsigned int bank) { AdlBank = bank; //Embedded banks are supports 128:128 GM set only - dynamic_percussion_offset = 128; - dynamic_melodic_banks.clear(); - dynamic_percussion_banks.clear(); + dynamic_banks.clear(); + + if(bank >= static_cast(maxAdlBanks())) + return; + + Bank *bank_pair[2] = + { + &dynamic_banks[0], + &dynamic_banks[PercussionTag] + }; + + for(unsigned i = 0; i < 256; ++i) + { + size_t meta = banks[bank][i]; + adlinsdata2 &ins = bank_pair[i / 128]->ins[i % 128]; + ins = adlinsdata2(adlins[meta]); + } } +static adlinsdata2 makeEmptyInstrument() +{ + adlinsdata2 ins; + memset(&ins, 0, sizeof(adlinsdata2)); + ins.flags = adlinsdata::Flag_NoSound; + return ins; +} + +const adlinsdata2 OPL3::emptyInstrument = makeEmptyInstrument(); OPL3::OPL3() : - dynamic_percussion_offset(128), - DynamicInstrumentTag(0x8000u), - DynamicMetaInstrumentTag(0x4000000u), NumCards(1), - AdlBank(0), NumFourOps(0), HighTremoloMode(false), HighVibratoMode(false), AdlPercussionMode(false), - LogarithmicVolumes(false), - //CartoonersVolumes(false), m_musicMode(MODE_MIDI), m_volumeScale(VOLUME_Generic) -{} - -void OPL3::Poke(size_t card, uint32_t index, uint32_t value) { - #ifdef ADLMIDI_HW_OPL - (void)card; - unsigned o = index >> 8; - unsigned port = OPLBase + o * 2; - - #ifdef __DJGPP__ - outportb(port, index); - for(unsigned c = 0; c < 6; ++c) inportb(port); - outportb(port + 1, value); - for(unsigned c = 0; c < 35; ++c) inportb(port); - #endif//__DJGPP__ - - #ifdef __WATCOMC__ - outp(port, index); - for(uint16_t c = 0; c < 6; ++c) inp(port); - outp(port + 1, value); - for(uint16_t c = 0; c < 35; ++c) inp(port); - #endif//__WATCOMC__ - - #else//ADLMIDI_HW_OPL - - #ifdef ADLMIDI_USE_DOSBOX_OPL - cards[card].WriteReg(index, static_cast(value)); - #else - OPL3_WriteReg(&cards[card], static_cast(index), static_cast(value)); - #endif - - #endif//ADLMIDI_HW_OPL +#ifdef DISABLE_EMBEDDED_BANKS + AdlBank = ~0u; +#else + setEmbeddedBank(0); +#endif } -void OPL3::PokeN(size_t card, uint16_t index, uint8_t value) +void OPL3::Poke(size_t card, uint16_t index, uint8_t value) { #ifdef ADLMIDI_HW_OPL (void)card; @@ -216,11 +200,7 @@ void OPL3::PokeN(size_t card, uint16_t index, uint8_t value) #endif//__WATCOMC__ #else - #ifdef ADLMIDI_USE_DOSBOX_OPL - cards[card].WriteReg(static_cast(index), value); - #else - OPL3_WriteReg(&cards[card], index, value); - #endif + cardsOP2[card]->writeReg(index, value); #endif } @@ -277,10 +257,9 @@ void OPL3::Touch_Real(unsigned c, unsigned volume, uint8_t brightness) volume = 63; size_t card = c / 23, cc = c % 23; - size_t i = ins[c]; + const adldata &adli = ins[c]; uint16_t o1 = Operators[cc * 2 + 0]; uint16_t o2 = Operators[cc * 2 + 1]; - const adldata &adli = GetAdlIns(i); uint8_t x = adli.modulator_40, y = adli.carrier_40; uint16_t mode = 1; // 2-op AM @@ -290,22 +269,22 @@ void OPL3::Touch_Real(unsigned c, unsigned volume, uint8_t brightness) } else if(four_op_category[c] == 1 || four_op_category[c] == 2) { - size_t i0, i1; + const adldata *i0, *i1; if(four_op_category[c] == 1) { - i0 = i; - i1 = ins[c + 3]; + i0 = &adli; + i1 = &ins[c + 3]; mode = 2; // 4-op xx-xx ops 1&2 } else { - i0 = ins[c - 3]; - i1 = i; + i0 = &ins[c - 3]; + i1 = &adli; mode = 6; // 4-op xx-xx ops 3&4 } - mode += (GetAdlIns(i0).feedconn & 1) + (GetAdlIns(i1).feedconn & 1) * 2; + mode += (i0->feedconn & 1) + (i1->feedconn & 1) * 2; } static const bool do_ops[10][2] = @@ -372,14 +351,13 @@ void OPL3::Touch(unsigned c, unsigned volume) // Volume maxes at 127*127*127 } }*/ -void OPL3::Patch(uint16_t c, size_t i) +void OPL3::Patch(uint16_t c, const adldata &adli) { uint16_t card = c / 23, cc = c % 23; static const uint8_t data[4] = {0x20, 0x60, 0x80, 0xE0}; - ins[c] = i; + ins[c] = adli; uint16_t o1 = Operators[cc * 2 + 0]; uint16_t o2 = Operators[cc * 2 + 1]; - const adldata &adli = GetAdlIns(i); unsigned x = adli.modulator_E862, y = adli.carrier_E862; for(unsigned a = 0; a < 4; ++a, x >>= 8, y >>= 8) @@ -395,7 +373,7 @@ void OPL3::Pan(unsigned c, unsigned value) unsigned card = c / 23, cc = c % 23; if(Channels[cc] != 0xFFF) - Poke(card, 0xC0 + Channels[cc], GetAdlIns(ins[c]).feedconn | value); + Poke(card, 0xC0 + Channels[cc], ins[c].feedconn | value); } void OPL3::Silence() // Silence all OPL channels. @@ -479,9 +457,8 @@ void OPL3::ChangeVolumeRangesModel(ADLMIDI_VolumeModels volumeModel) m_volumeScale = OPL3::VOLUME_Generic; break; - case ADLMIDI_VolumeModel_CMF: - LogarithmicVolumes = true; - m_volumeScale = OPL3::VOLUME_CMF; + case ADLMIDI_VolumeModel_NativeOPL3: + m_volumeScale = OPL3::VOLUME_NATIVE; break; case ADLMIDI_VolumeModel_DMX: @@ -498,26 +475,36 @@ void OPL3::ChangeVolumeRangesModel(ADLMIDI_VolumeModels volumeModel) } } -void OPL3::Reset(unsigned long PCM_RATE) +#ifndef ADLMIDI_HW_OPL +void OPL3::ClearChips() { - #ifndef ADLMIDI_HW_OPL - #ifdef ADLMIDI_USE_DOSBOX_OPL - DBOPL::Handler emptyChip; //Constructors inside are will initialize necessary fields - #else - _opl3_chip emptyChip; - std::memset(&emptyChip, 0, sizeof(_opl3_chip)); - #endif - cards.clear(); - #endif + for(size_t i = 0; i < cardsOP2.size(); i++) + cardsOP2[i].reset(NULL); + cardsOP2.clear(); +} +#endif + +void OPL3::Reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler) +{ +#ifndef ADLMIDI_HW_OPL + ClearChips(); +#else + (void)emulator; (void)PCM_RATE; +#endif +#if !defined(ADLMIDI_AUDIO_TICK_HANDLER) + (void)audioTickHandler; +#endif ins.clear(); pit.clear(); regBD.clear(); - #ifndef ADLMIDI_HW_OPL - cards.resize(NumCards, emptyChip); - #endif + +#ifndef ADLMIDI_HW_OPL + cardsOP2.resize(NumCards, AdlMIDI_SPtr()); +#endif + NumChannels = NumCards * 23; - ins.resize(NumChannels, 189); + ins.resize(NumChannels, adl[adlDefaultNumber]); pit.resize(NumChannels, 0); regBD.resize(NumCards, 0); four_op_category.resize(NumChannels, 0); @@ -536,24 +523,45 @@ void OPL3::Reset(unsigned long PCM_RATE) }; unsigned fours = NumFourOps; - for(unsigned card = 0; card < NumCards; ++card) + for(size_t i = 0; i < NumCards; ++i) { - #ifndef ADLMIDI_HW_OPL - # ifdef ADLMIDI_USE_DOSBOX_OPL - cards[card].Init(PCM_RATE); - # else - OPL3_Reset(&cards[card], static_cast(PCM_RATE)); - # endif - #endif +#ifndef ADLMIDI_HW_OPL + OPLChipBase *chip; + switch(emulator) + { + default: +#ifndef ADLMIDI_DISABLE_NUKED_EMULATOR + case ADLMIDI_EMU_NUKED: /* Latest Nuked OPL3 */ + chip = new NukedOPL3; + break; + case ADLMIDI_EMU_NUKED_174: /* Old Nuked OPL3 1.4.7 modified and optimized */ + chip = new NukedOPL3v174; + break; +#endif +#ifndef ADLMIDI_DISABLE_DOSBOX_EMULATOR + case ADLMIDI_EMU_DOSBOX: + chip = new DosBoxOPL3; + break; +#endif + } + cardsOP2[i].reset(chip); + chip->setChipId(i); + chip->setRate((uint32_t)PCM_RATE); + if(runAtPcmRate) + chip->setRunningAtPcmRate(true); +# if defined(ADLMIDI_AUDIO_TICK_HANDLER) + chip->setAudioTickHandlerInstance(audioTickHandler); +# endif +#endif // ADLMIDI_HW_OPL - for(unsigned a = 0; a < 18; ++a) Poke(card, 0xB0 + Channels[a], 0x00); + for(unsigned a = 0; a < 18; ++a) Poke(i, 0xB0 + Channels[a], 0x00); for(unsigned a = 0; a < sizeof(data) / sizeof(*data); a += 2) - PokeN(card, data[a], static_cast(data[a + 1])); - Poke(card, 0x0BD, regBD[card] = (HighTremoloMode * 0x80 - + HighVibratoMode * 0x40 - + AdlPercussionMode * 0x20)); + Poke(i, data[a], static_cast(data[a + 1])); + Poke(i, 0x0BD, regBD[i] = (HighTremoloMode * 0x80 + + HighVibratoMode * 0x40 + + AdlPercussionMode * 0x20)); unsigned fours_this_card = std::min(fours, 6u); - Poke(card, 0x104, (1 << fours_this_card) - 1); + Poke(i, 0x104, (1 << fours_this_card) - 1); //fprintf(stderr, "Card %u: %u four-ops.\n", card, fours_this_card); fours -= fours_this_card; } diff --git a/src/sound/adlmidi/adlmidi_private.cpp b/src/sound/adlmidi/adlmidi_private.cpp index 1f3cb7ddd..1ee7c4a33 100644 --- a/src/sound/adlmidi/adlmidi_private.cpp +++ b/src/sound/adlmidi/adlmidi_private.cpp @@ -25,6 +25,13 @@ std::string ADLMIDI_ErrorString; +// Generator callback on audio rate ticks + +void adl_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate) +{ + reinterpret_cast(instance)->AudioTick(chipId, rate); +} + int adlRefreshNumCards(ADL_MIDIPlayer *device) { unsigned n_fourop[2] = {0, 0}, n_total[2] = {0, 0}; @@ -34,19 +41,22 @@ int adlRefreshNumCards(ADL_MIDIPlayer *device) if(play->opl.AdlBank == ~0u) { //For custom bank - for(size_t a = 0; a < play->opl.dynamic_metainstruments.size(); ++a) + OPL3::BankMap::iterator it = play->opl.dynamic_banks.begin(); + OPL3::BankMap::iterator end = play->opl.dynamic_banks.end(); + for(; it != end; ++it) { - size_t div = (a >= play->opl.dynamic_percussion_offset) ? 1 : 0; - ++n_total[div]; - adlinsdata &ins = play->opl.dynamic_metainstruments[a]; - if((ins.adlno1 != ins.adlno2) && ((ins.flags & adlinsdata::Flag_Pseudo4op) == 0)) - ++n_fourop[div]; + uint16_t bank = it->first; + unsigned div = (bank & OPL3::PercussionTag) ? 1 : 0; + for(unsigned i = 0; i < 128; ++i) + { + adlinsdata2 &ins = it->second.ins[i]; + if(ins.flags & adlinsdata::Flag_NoSound) + continue; + if((ins.adl[0] != ins.adl[1]) && ((ins.flags & adlinsdata::Flag_Pseudo4op) == 0)) + ++n_fourop[div]; + ++n_total[div]; + } } - - play->m_setup.NumFourOps = - (n_fourop[0] >= 128 * 7 / 8) ? play->m_setup.NumCards * 6 - : (n_fourop[0] < 128 * 1 / 8) ? (n_fourop[1] > 0 ? 4 : 0) - : (play->m_setup.NumCards == 1 ? 1 : play->m_setup.NumCards * 4); } else { @@ -57,27 +67,34 @@ int adlRefreshNumCards(ADL_MIDIPlayer *device) if(insno == 198) continue; ++n_total[a / 128]; - const adlinsdata &ins = adlins[insno]; - if((ins.adlno1 != ins.adlno2) && ((ins.flags & adlinsdata::Flag_Pseudo4op) == 0)) + adlinsdata2 ins(adlins[insno]); + if(ins.flags & adlinsdata::Flag_Real4op) ++n_fourop[a / 128]; } - - play->m_setup.NumFourOps = - (n_fourop[0] >= (n_total[0] % 128) * 7 / 8) ? play->m_setup.NumCards * 6 - : (n_fourop[0] < (n_total[0] % 128) * 1 / 8) ? 0 - : (play->m_setup.NumCards == 1 ? 1 : play->m_setup.NumCards * 4); } - play->opl.NumFourOps = play->m_setup.NumFourOps; + unsigned numFourOps = 0; - if(n_fourop[0] >= n_total[0] * 15 / 16 && play->m_setup.NumFourOps == 0) - { - play->setErrorString("ERROR: You have selected a bank that consists almost exclusively of four-op patches.\n" - " The results (silence + much cpu load) would be probably\n" - " not what you want, therefore ignoring the request.\n"); - return -1; - } + // All 2ops (no 4ops) + if((n_fourop[0] == 0) && (n_fourop[1] == 0)) + numFourOps = 0; + // All 2op melodics and Some (or All) 4op drums + else if((n_fourop[0] == 0) && (n_fourop[1] > 0)) + numFourOps = 2; + // Many 4op melodics + else if((n_fourop[0] >= (n_total[0] * 7) / 8)) + numFourOps = 6; + // Few 4op melodics + else if(n_fourop[0] > 0) + numFourOps = 4; + +/* //Old formula + unsigned NumFourOps = ((n_fourop[0] == 0) && (n_fourop[1] == 0)) ? 0 + : (n_fourop[0] >= (n_total[0] * 7) / 8) ? play->m_setup.NumCards * 6 + : (play->m_setup.NumCards == 1 ? 1 : play->m_setup.NumCards * 4); +*/ + + play->opl.NumFourOps = play->m_setup.NumFourOps = (numFourOps * play->m_setup.NumCards); return 0; } - diff --git a/src/sound/adlmidi/adlmidi_private.hpp b/src/sound/adlmidi/adlmidi_private.hpp index eace3a736..0e63b5a61 100644 --- a/src/sound/adlmidi/adlmidi_private.hpp +++ b/src/sound/adlmidi/adlmidi_private.hpp @@ -35,6 +35,9 @@ # endif #endif +// Require declarations of unstable API for extern "C" +#define ADLMIDI_UNSTABLE_API + #ifdef _WIN32 #define NOMINMAX #endif @@ -87,12 +90,14 @@ typedef int32_t ssize_t; #include #include #include +#include #include // vector #include // deque #include // exp, log, ceil #if defined(__WATCOMC__) #include // round, sqrt #endif +#include #include #include #include // numeric_limit @@ -104,22 +109,31 @@ typedef int32_t ssize_t; #include #include -#ifdef _MSC_VER -#pragma warning(disable:4319) -#pragma warning(disable:4267) -#pragma warning(disable:4244) -#pragma warning(disable:4146) -#pragma warning(disable:4800) +/* + * Workaround for some compilers are has no those macros in their headers! + */ +#ifndef INT8_MIN +#define INT8_MIN (-0x7f - 1) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-0x7fff - 1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-0x7fffffff - 1) +#endif +#ifndef INT8_MAX +#define INT8_MAX 0x7f +#endif +#ifndef INT16_MAX +#define INT16_MAX 0x7fff +#endif +#ifndef INT32_MAX +#define INT32_MAX 0x7fffffff #endif #include "fraction.hpp" - #ifndef ADLMIDI_HW_OPL -#ifdef ADLMIDI_USE_DOSBOX_OPL -#include "dbopl.h" -#else -#include "nukedopl3.h" -#endif +#include "chips/opl_chip_base.h" #endif #include "adldata.hh" @@ -127,46 +141,63 @@ typedef int32_t ssize_t; #ifndef ADLMIDI_DISABLE_CPP_EXTRAS #include "adlmidi.hpp" //Extra C++ API #endif +#include "adlmidi_ptr.hpp" +#include "adlmidi_bankmap.h" #define ADL_UNUSED(x) (void)x +#define OPL_PANNING_LEFT 0x10 +#define OPL_PANNING_RIGHT 0x20 +#define OPL_PANNING_BOTH 0x30 + extern std::string ADLMIDI_ErrorString; /* - Smart pointer for C heaps, created with malloc() call. - FAQ: Why not std::shared_ptr? Because of Android NDK now doesn't supports it + Sample conversions to various formats */ -template -class AdlMIDI_CPtr +template +inline Real adl_cvtReal(int32_t x) { - PTR *m_p; -public: - AdlMIDI_CPtr() : m_p(NULL) {} - ~AdlMIDI_CPtr() - { - reset(NULL); - } + return x * ((Real)1 / INT16_MAX); +} - void reset(PTR *p = NULL) - { - if(m_p) - free(m_p); - m_p = p; - } +inline int32_t adl_cvtS16(int32_t x) +{ + x = (x < INT16_MIN) ? (INT16_MIN) : x; + x = (x > INT16_MAX) ? (INT16_MAX) : x; + return x; +} - PTR *get() - { - return m_p; - } - PTR &operator*() - { - return *m_p; - } - PTR *operator->() - { - return m_p; - } -}; +inline int32_t adl_cvtS8(int32_t x) +{ + return adl_cvtS16(x) / 256; +} +inline int32_t adl_cvtS24(int32_t x) +{ + return adl_cvtS16(x) * 256; +} +inline int32_t adl_cvtS32(int32_t x) +{ + return adl_cvtS16(x) * 65536; +} +inline int32_t adl_cvtU16(int32_t x) +{ + return adl_cvtS16(x) - INT16_MIN; +} +inline int32_t adl_cvtU8(int32_t x) +{ + return (adl_cvtS16(x) / 256) - INT8_MIN; +} +inline int32_t adl_cvtU24(int32_t x) +{ + enum { int24_min = -(1 << 23) }; + return adl_cvtS24(x) - int24_min; +} +inline int32_t adl_cvtU32(int32_t x) +{ + // unsigned operation because overflow on signed integers is undefined + return (uint32_t)adl_cvtS32(x) - (uint32_t)INT32_MIN; +} class MIDIplay; struct ADL_MIDIPlayer; @@ -179,34 +210,26 @@ public: char ____padding[4]; ADL_MIDIPlayer *_parent; #ifndef ADLMIDI_HW_OPL -# ifdef ADLMIDI_USE_DOSBOX_OPL - std::vector cards; -# else - std::vector<_opl3_chip> cards; -# endif + std::vector > cardsOP2; #endif private: - std::vector ins; // index to adl[], cached, needed by Touch() + std::vector ins; // patch data, cached, needed by Touch() std::vector pit; // value poked to B0, cached, needed by NoteOff)( std::vector regBD; friend int adlRefreshNumCards(ADL_MIDIPlayer *device); - //! Meta information about every instrument - std::vector dynamic_metainstruments; // Replaces adlins[] when CMF file - //! Raw instrument data ready to be sent to the chip - std::vector dynamic_instruments; // Replaces adl[] when CMF file - size_t dynamic_percussion_offset; - - typedef std::map BankMap; - BankMap dynamic_melodic_banks; - BankMap dynamic_percussion_banks; - const unsigned DynamicInstrumentTag /* = 0x8000u*/, - DynamicMetaInstrumentTag /* = 0x4000000u*/; - const adlinsdata &GetAdlMetaIns(size_t n); - size_t GetAdlMetaNumber(size_t midiins); - const adldata &GetAdlIns(size_t insno); +public: + struct Bank + { + adlinsdata2 ins[128]; + }; + typedef BasicBankMap BankMap; + BankMap dynamic_banks; + AdlBankSetup dynamic_bank_setup; public: void setEmbeddedBank(unsigned int bank); + static const adlinsdata2 emptyInstrument; + enum { PercussionTag = 1 << 15 }; //! Total number of running concurrent emulated chips unsigned int NumCards; @@ -222,8 +245,10 @@ public: bool AdlPercussionMode; //! Carriers-only are scaled by default by volume level. This flag will tell to scale modulators too. bool ScaleModulators; - //! Required to play CMF files. Can be turned on by using of "CMF" volume model - bool LogarithmicVolumes; + //! Run emulator at PCM rate if that possible. Reduces sounding accuracy, but decreases CPU usage on lower rates. + bool runAtPcmRate; + // ! Required to play CMF files. Can be turned on by using of "CMF" volume model + //bool LogarithmicVolumes; //[REPLACED WITH "m_volumeScale == VOLUME_NATIVE", DEPRECATED!!!] // ! Required to play EA-MUS files [REPLACED WITH "m_musicMode", DEPRECATED!!!] //bool CartoonersVolumes; enum MusicMode @@ -239,7 +264,7 @@ public: enum VolumesScale { VOLUME_Generic, - VOLUME_CMF, + VOLUME_NATIVE, VOLUME_DMX, VOLUME_APOGEE, VOLUME_9X @@ -255,21 +280,23 @@ public: // 7 = percussion Hihat // 8 = percussion slave - void Poke(size_t card, uint32_t index, uint32_t value); - void PokeN(size_t card, uint16_t index, uint8_t value); + void Poke(size_t card, uint16_t index, uint8_t value); void NoteOff(size_t c); void NoteOn(unsigned c, double hertz); void Touch_Real(unsigned c, unsigned volume, uint8_t brightness = 127); //void Touch(unsigned c, unsigned volume) - void Patch(uint16_t c, size_t i); + void Patch(uint16_t c, const adldata &adli); void Pan(unsigned c, unsigned value); void Silence(); void updateFlags(); void updateDeepFlags(); void ChangeVolumeRangesModel(ADLMIDI_VolumeModels volumeModel); - void Reset(unsigned long PCM_RATE); + #ifndef ADLMIDI_HW_OPL + void ClearChips(); + #endif + void Reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler); }; @@ -455,7 +482,7 @@ public: bool eof() { if(fp) - return std::feof(fp); + return (std::feof(fp) != 0); else return mp_tell >= mp_size; } @@ -473,9 +500,15 @@ public: uint8_t bank_lsb, bank_msb; uint8_t patch; uint8_t volume, expression; - uint8_t panning, vibrato, sustain; + uint8_t panning, vibrato, aftertouch, sustain; + //! Per note Aftertouch values + uint8_t noteAftertouch[128]; + //! Is note aftertouch has any non-zero value + bool noteAfterTouchInUse; char ____padding[6]; - double bend, bendsense; + int bend; + double bendsense; + int bendsense_lsb, bendsense_msb; double vibpos, vibspeed, vibdepth; int64_t vibdelay; uint8_t lastlrpn, lastmrpn; @@ -484,66 +517,220 @@ public: bool is_xg_percussion; struct NoteInfo { + uint8_t note; + bool active; // Current pressure uint8_t vol; - char ____padding[1]; + // Note vibrato (a part of Note Aftertouch feature) + uint8_t vibrato; // Tone selected on noteon: int16_t tone; char ____padding2[4]; - // Patch selected on noteon; index to banks[AdlBank][] + // Patch selected on noteon; index to bank.ins[] size_t midiins; - // Index to physical adlib data structure, adlins[] - size_t insmeta; + // Patch selected + const adlinsdata2 *ains; + enum + { + MaxNumPhysChans = 2, + MaxNumPhysItemCount = MaxNumPhysChans, + }; struct Phys { + //! Destination chip channel + uint16_t chip_chan; //! ins, inde to adl[] - size_t insId; + adldata ains; //! Is this voice must be detunable? bool pseudo4op; + void assign(const Phys &oth) + { + ains = oth.ains; + pseudo4op = oth.pseudo4op; + } bool operator==(const Phys &oth) const { - return (insId == oth.insId) && (pseudo4op == oth.pseudo4op); + return (ains == oth.ains) && (pseudo4op == oth.pseudo4op); } bool operator!=(const Phys &oth) const { return !operator==(oth); } }; - typedef std::map PhysMap; - // List of OPL3 channels it is currently occupying. - std::map phys; + //! List of OPL3 channels it is currently occupying. + Phys chip_channels[MaxNumPhysItemCount]; + //! Count of used channels. + unsigned chip_channels_count; + // + Phys *phys_find(unsigned chip_chan) + { + Phys *ph = NULL; + for(unsigned i = 0; i < chip_channels_count && !ph; ++i) + if(chip_channels[i].chip_chan == chip_chan) + ph = &chip_channels[i]; + return ph; + } + Phys *phys_find_or_create(uint16_t chip_chan) + { + Phys *ph = phys_find(chip_chan); + if(!ph) { + if(chip_channels_count < MaxNumPhysItemCount) { + ph = &chip_channels[chip_channels_count++]; + ph->chip_chan = chip_chan; + } + } + return ph; + } + Phys *phys_ensure_find_or_create(uint16_t chip_chan) + { + Phys *ph = phys_find_or_create(chip_chan); + assert(ph); + return ph; + } + void phys_erase_at(const Phys *ph) + { + intptr_t pos = ph - chip_channels; + assert(pos < static_cast(chip_channels_count)); + for(intptr_t i = pos + 1; i < static_cast(chip_channels_count); ++i) + chip_channels[i - 1] = chip_channels[i]; + --chip_channels_count; + } + void phys_erase(unsigned chip_chan) + { + Phys *ph = phys_find(chip_chan); + if(ph) + phys_erase_at(ph); + } }; - typedef std::map activenotemap_t; - typedef activenotemap_t::iterator activenoteiterator; char ____padding2[5]; - activenotemap_t activenotes; + NoteInfo activenotes[128]; + + struct activenoteiterator + { + explicit activenoteiterator(NoteInfo *info = 0) + : ptr(info) {} + activenoteiterator &operator++() + { + if(ptr->note == 127) + ptr = 0; + else + for(++ptr; ptr && !ptr->active;) + ptr = (ptr->note == 127) ? 0 : (ptr + 1); + return *this; + } + activenoteiterator operator++(int) + { + activenoteiterator pos = *this; + ++*this; + return pos; + } + NoteInfo &operator*() const + { return *ptr; } + NoteInfo *operator->() const + { return ptr; } + bool operator==(activenoteiterator other) const + { return ptr == other.ptr; } + bool operator!=(activenoteiterator other) const + { return ptr != other.ptr; } + operator NoteInfo *() const + { return ptr; } + private: + NoteInfo *ptr; + }; + + activenoteiterator activenotes_begin() + { + activenoteiterator it(activenotes); + return (it->active) ? it : ++it; + } + + activenoteiterator activenotes_find(uint8_t note) + { + assert(note < 128); + return activenoteiterator( + activenotes[note].active ? &activenotes[note] : 0); + } + + activenoteiterator activenotes_ensure_find(uint8_t note) + { + activenoteiterator it = activenotes_find(note); + assert(it); + return it; + } + + std::pair activenotes_insert(uint8_t note) + { + assert(note < 128); + NoteInfo &info = activenotes[note]; + bool inserted = !info.active; + if(inserted) info.active = true; + return std::pair(activenoteiterator(&info), inserted); + } + + void activenotes_erase(activenoteiterator pos) + { + if(pos) + pos->active = false; + } + + bool activenotes_empty() + { + return !activenotes_begin(); + } + + void activenotes_clear() + { + for(uint8_t i = 0; i < 128; ++i) { + activenotes[i].note = i; + activenotes[i].active = false; + } + } + void reset() { - portamento = 0; + resetAllControllers(); + patch = 0; + vibpos = 0; bank_lsb = 0; bank_msb = 0; - patch = 0; - volume = 100; - expression = 127; - panning = 0x30; - vibrato = 0; - sustain = 0; - bend = 0.0; - bendsense = 2 / 8192.0; - vibpos = 0; - vibspeed = 2 * 3.141592653 * 5.0; - vibdepth = 0.5 / 127; - vibdelay = 0; lastlrpn = 0; lastmrpn = 0; nrpn = false; - brightness = 127; is_xg_percussion = false; } - MIDIchannel() - : activenotes() + void resetAllControllers() { + bend = 0; + bendsense_msb = 2; + bendsense_lsb = 0; + updateBendSensitivity(); + volume = 100; + expression = 127; + sustain = 0; + vibrato = 0; + aftertouch = 0; + std::memset(noteAftertouch, 0, 128); + noteAfterTouchInUse = false; + vibspeed = 2 * 3.141592653 * 5.0; + vibdepth = 0.5 / 127; + vibdelay = 0; + panning = OPL_PANNING_BOTH; + portamento = 0; + brightness = 127; + } + bool hasVibrato() + { + return (vibrato > 0) || (aftertouch > 0) || noteAfterTouchInUse; + } + void updateBendSensitivity() + { + int cent = bendsense_msb * 128 + bendsense_lsb; + bendsense = cent * (1.0 / (128 * 8192)); + } + MIDIchannel() + { + activenotes_clear(); reset(); } }; @@ -551,36 +738,70 @@ public: // Additional information about OPL3 channels struct AdlChannel { - // For collisions struct Location { uint16_t MidCh; uint8_t note; - bool operator==(const Location &b) const - { - return MidCh == b.MidCh && note == b.note; - } - bool operator< (const Location &b) const - { - return MidCh < b.MidCh || (MidCh == b.MidCh && note < b.note); - } - char ____padding[1]; + bool operator==(const Location &l) const + { return MidCh == l.MidCh && note == l.note; } + bool operator!=(const Location &l) const + { return !operator==(l); } }; struct LocationData { + LocationData *prev, *next; + Location loc; bool sustained; char ____padding[7]; MIDIchannel::NoteInfo::Phys ins; // a copy of that in phys[] + //! Has fixed sustain, don't iterate "on" timeout + bool fixed_sustain; + //! Timeout until note will be allowed to be killed by channel manager while it is on int64_t kon_time_until_neglible; int64_t vibdelay; }; - typedef std::map users_t; - users_t users; // If the channel is keyoff'd int64_t koff_time_until_neglible; + + enum { users_max = 128 }; + LocationData *users_first, *users_free_cells; + LocationData users_cells[users_max]; + unsigned users_size; + + bool users_empty() const; + LocationData *users_find(Location loc); + LocationData *users_allocate(); + LocationData *users_find_or_create(Location loc); + LocationData *users_insert(const LocationData &x); + void users_erase(LocationData *user); + void users_clear(); + void users_assign(const LocationData *users, size_t count); + // For channel allocation: - AdlChannel(): users(), koff_time_until_neglible(0) { } + AdlChannel(): koff_time_until_neglible(0) + { + users_clear(); + } + + AdlChannel(const AdlChannel &oth): koff_time_until_neglible(oth.koff_time_until_neglible) + { + if(oth.users_first) + { + users_first = NULL; + users_assign(oth.users_first, oth.users_size); + } + else + users_clear(); + } + + AdlChannel &operator=(const AdlChannel &oth) + { + koff_time_until_neglible = oth.koff_time_until_neglible; + users_assign(oth.users_first, oth.users_size); + return *this; + } + void AddAge(int64_t ms); }; @@ -713,6 +934,8 @@ public: struct Setup { + int emulator; + bool runAtPcmRate; unsigned int AdlBank; unsigned int NumFourOps; unsigned int NumCards; @@ -724,6 +947,7 @@ public: //unsigned int SkipForward; bool loopingIsEnabled; int ScaleModulators; + bool fullRangeBrightnessCC74; double delay; double carry; @@ -760,6 +984,11 @@ private: char ____padding[7]; std::vector ch; + //! Counter of arpeggio processing + size_t m_arpeggioCounter; + + //! Audio tick counter + uint32_t m_audioTickCounter; #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER std::vector > TrackData; @@ -832,11 +1061,25 @@ public: #endif OPL3 opl; - int16_t outBuf[1024]; + int32_t outBuf[1024]; Setup m_setup; +#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER + /** + * @brief Utility function to read Big-Endian integer from raw binary data + * @param buffer Pointer to raw binary buffer + * @param nbytes Count of bytes to parse integer + * @return Extracted unsigned integer + */ static uint64_t ReadBEint(const void *buffer, size_t nbytes); + + /** + * @brief Utility function to read Little-Endian integer from raw binary data + * @param buffer Pointer to raw binary buffer + * @param nbytes Count of bytes to parse integer + * @return Extracted unsigned integer + */ static uint64_t ReadLEint(const void *buffer, size_t nbytes); /** @@ -853,6 +1096,7 @@ public: * @return Unsigned integer that conains parsed variable-length value */ uint64_t ReadVarLenEx(uint8_t **ptr, uint8_t *end, bool &ok); +#endif bool LoadBank(const std::string &filename); bool LoadBank(const void *data, size_t size); @@ -943,6 +1187,9 @@ public: void realTime_panic(); + // Audio rate tick handler + void AudioTick(uint32_t chipId, uint32_t rate); + private: enum { @@ -951,7 +1198,9 @@ private: Upd_Volume = 0x4, Upd_Pitch = 0x8, Upd_All = Upd_Pan + Upd_Volume + Upd_Pitch, - Upd_Off = 0x20 + Upd_Off = 0x20, + Upd_Mute = 0x40, + Upt_OffMute = Upd_Off + Upd_Mute }; void NoteUpdate(uint16_t MidCh, @@ -966,7 +1215,7 @@ private: // Determine how good a candidate this adlchannel // would be for playing a note from this instrument. - int64_t CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t /*MidCh*/) const; + int64_t CalculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t /*MidCh*/) const; // A new note will be played on this channel using this instrument. // Kill existing notes on this channel (or don't, if we do arpeggio) @@ -974,7 +1223,7 @@ private: void KillOrEvacuate( size_t from_channel, - AdlChannel::users_t::iterator j, + AdlChannel::LocationData *j, MIDIchannel::activenoteiterator i); void Panic(); void KillSustainingNotes(int32_t MidCh = -1, int32_t this_adlchn = -1); @@ -1009,6 +1258,7 @@ struct FourChars }; */ +extern void adl_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate); extern int adlRefreshNumCards(ADL_MIDIPlayer *device); diff --git a/src/sound/adlmidi/adlmidi_ptr.hpp b/src/sound/adlmidi/adlmidi_ptr.hpp new file mode 100644 index 000000000..7d1086b5f --- /dev/null +++ b/src/sound/adlmidi/adlmidi_ptr.hpp @@ -0,0 +1,217 @@ +/* + * libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation + * + * Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma + * ADLMIDI Library API: Copyright (c) 2015-2018 Vitaly Novichkov + * + * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation: + * http://iki.fi/bisqwit/source/adlmidi.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ADLMIDI_PTR_HPP_THING +#define ADLMIDI_PTR_HPP_THING + +#include // swap +#include +#include + +/* + Generic deleters for smart pointers + */ +template +struct ADLMIDI_DefaultDelete +{ + void operator()(T *x) { delete x; } +}; +template +struct ADLMIDI_DefaultArrayDelete +{ + void operator()(T *x) { delete[] x; } +}; +struct ADLMIDI_CDelete +{ + void operator()(void *x) { free(x); } +}; + +/* + Safe unique pointer for C++98, non-copyable but swappable. +*/ +template< class T, class Deleter = ADLMIDI_DefaultDelete > +class AdlMIDI_UPtr +{ + T *m_p; +public: + explicit AdlMIDI_UPtr(T *p) + : m_p(p) {} + ~AdlMIDI_UPtr() + { + reset(); + } + + void reset(T *p = NULL) + { + if(p != m_p) { + if(m_p) { + Deleter del; + del(m_p); + } + m_p = p; + } + } + + void swap(AdlMIDI_UPtr &other) + { + std::swap(m_p, other.m_p); + } + + T *get() const + { + return m_p; + } + T &operator*() const + { + return *m_p; + } + T *operator->() const + { + return m_p; + } + T &operator[](size_t index) const + { + return m_p[index]; + } +private: + AdlMIDI_UPtr(const AdlMIDI_UPtr &); + AdlMIDI_UPtr &operator=(const AdlMIDI_UPtr &); +}; + +template +void swap(AdlMIDI_UPtr &a, AdlMIDI_UPtr &b) +{ + a.swap(b); +} + +/** + Unique pointer for arrays. + */ +template +class AdlMIDI_UPtrArray : + public AdlMIDI_UPtr< T, ADLMIDI_DefaultArrayDelete > +{ +public: + explicit AdlMIDI_UPtrArray(T *p = NULL) + : AdlMIDI_UPtr< T, ADLMIDI_DefaultArrayDelete >(p) {} +}; + +/** + Unique pointer for C memory. + */ +template +class AdlMIDI_CPtr : + public AdlMIDI_UPtr< T, ADLMIDI_CDelete > +{ +public: + explicit AdlMIDI_CPtr(T *p = NULL) + : AdlMIDI_UPtr< T, ADLMIDI_CDelete >(p) {} +}; + +/* + Shared pointer with non-atomic counter + FAQ: Why not std::shared_ptr? Because of Android NDK now doesn't supports it +*/ +template< class T, class Deleter = ADLMIDI_DefaultDelete > +class AdlMIDI_SPtr +{ + T *m_p; + size_t *m_counter; +public: + explicit AdlMIDI_SPtr(T *p = NULL) + : m_p(p), m_counter(p ? new size_t(1) : NULL) {} + ~AdlMIDI_SPtr() + { + reset(NULL); + } + + AdlMIDI_SPtr(const AdlMIDI_SPtr &other) + : m_p(other.m_p), m_counter(other.m_counter) + { + if(m_counter) + ++*m_counter; + } + + AdlMIDI_SPtr &operator=(const AdlMIDI_SPtr &other) + { + if(this == &other) + return *this; + reset(); + m_p = other.m_p; + m_counter = other.m_counter; + if(m_counter) + ++*m_counter; + return *this; + } + + void reset(T *p = NULL) + { + if(p != m_p) { + if(m_p && --*m_counter == 0) { + Deleter del; + del(m_p); + if(!p) { + delete m_counter; + m_counter = NULL; + } + } + m_p = p; + if(p) { + if(!m_counter) + m_counter = new size_t; + *m_counter = 1; + } + } + } + + T *get() const + { + return m_p; + } + T &operator*() const + { + return *m_p; + } + T *operator->() const + { + return m_p; + } + T &operator[](size_t index) const + { + return m_p[index]; + } +}; + +/** + Shared pointer for arrays. + */ +template +class AdlMIDI_SPtrArray : + public AdlMIDI_SPtr< T, ADLMIDI_DefaultArrayDelete > +{ +public: + explicit AdlMIDI_SPtrArray(T *p = NULL) + : AdlMIDI_SPtr< T, ADLMIDI_DefaultArrayDelete >(p) {} +}; + +#endif //ADLMIDI_PTR_HPP_THING diff --git a/src/sound/adlmidi/chips/dosbox/dbopl.cpp b/src/sound/adlmidi/chips/dosbox/dbopl.cpp new file mode 100644 index 000000000..7d78c5f05 --- /dev/null +++ b/src/sound/adlmidi/chips/dosbox/dbopl.cpp @@ -0,0 +1,1618 @@ +/* + * Copyright (C) 2002-2018 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + DOSBox implementation of a combined Yamaha YMF262 and Yamaha YM3812 emulator. + Enabling the opl3 bit will switch the emulator to stereo opl3 output instead of regular mono opl2 + Except for the table generation it's all integer math + Can choose different types of generators, using muls and bigger tables, try different ones for slower platforms + The generation was based on the MAME implementation but tried to have it use less memory and be faster in general + MAME uses much bigger envelope tables and this will be the biggest cause of it sounding different at times + + //TODO Don't delay first operator 1 sample in opl3 mode + //TODO Maybe not use class method pointers but a regular function pointers with operator as first parameter + //TODO Fix panning for the Percussion channels, would any opl3 player use it and actually really change it though? + //TODO Check if having the same accuracy in all frequency multipliers sounds better or not + + //DUNNO Keyon in 4op, switch to 2op without keyoff. +*/ + + + +#include +#include +#include +#include "dbopl.h" + +#if defined(__GNUC__) && __GNUC__ > 3 +#define INLINE inline __attribute__((__always_inline__)) +#elif defined(_MSC_VER) +#define INLINE __forceinline +#else +#define INLINE inline +#endif + +#if defined(__GNUC__) +#if !defined(__clang__) +#define GCC_LIKELY(x) __builtin_expect(x, 1) +#define GCC_UNLIKELY(x) __builtin_expect(x, 0) +#else // !defined(__clang__) +#if !defined (__c2__) && defined(__has_builtin) +#if __has_builtin(__builtin_expect) +#define GCC_LIKELY(x) __builtin_expect(x, 1) +#define GCC_UNLIKELY(x) __builtin_expect(x, 0) +#endif // __has_builtin(__builtin_expect) +#endif // !defined (__c2__) && defined(__has_builtin) +#endif // !defined(__clang__) +#endif // defined(__GNUC__) + +#if !defined(GCC_LIKELY) +#define GCC_LIKELY(x) (x) +#define GCC_UNLIKELY(x) (x) +#endif + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +namespace DBOPL { + +#define OPLRATE ((double)(14318180.0 / 288.0)) +#define TREMOLO_TABLE 52 + +//Try to use most precision for frequencies +//Else try to keep different waves in synch +//#define WAVE_PRECISION 1 +#ifndef WAVE_PRECISION +//Wave bits available in the top of the 32bit range +//Original adlib uses 10.10, we use 10.22 +#define WAVE_BITS 10 +#else +//Need some extra bits at the top to have room for octaves and frequency multiplier +//We support to 8 times lower rate +//128 * 15 * 8 = 15350, 2^13.9, so need 14 bits +#define WAVE_BITS 14 +#endif +#define WAVE_SH ( 32 - WAVE_BITS ) +#define WAVE_MASK ( ( 1 << WAVE_SH ) - 1 ) + +//Use the same accuracy as the waves +#define LFO_SH ( WAVE_SH - 10 ) +//LFO is controlled by our tremolo 256 sample limit +#define LFO_MAX ( 256 << ( LFO_SH ) ) + + +//Maximum amount of attenuation bits +//Envelope goes to 511, 9 bits +#if (DBOPL_WAVE == WAVE_TABLEMUL ) +//Uses the value directly +#define ENV_BITS ( 9 ) +#else +//Add 3 bits here for more accuracy and would have to be shifted up either way +#define ENV_BITS ( 9 ) +#endif +//Limits of the envelope with those bits and when the envelope goes silent +#define ENV_MIN 0 +#define ENV_EXTRA ( ENV_BITS - 9 ) +#define ENV_MAX ( 511 << ENV_EXTRA ) +#define ENV_LIMIT ( ( 12 * 256) >> ( 3 - ENV_EXTRA ) ) +#define ENV_SILENT( _X_ ) ( (_X_) >= ENV_LIMIT ) + +//Attack/decay/release rate counter shift +#define RATE_SH 24 +#define RATE_MASK ( ( 1 << RATE_SH ) - 1 ) +//Has to fit within 16bit lookuptable +#define MUL_SH 16 + +//Check some ranges +#if ENV_EXTRA > 3 +#error Too many envelope bits +#endif + + +//How much to substract from the base value for the final attenuation +static const Bit8u KslCreateTable[16] = { + //0 will always be be lower than 7 * 8 + 64, 32, 24, 19, + 16, 12, 11, 10, + 8, 6, 5, 4, + 3, 2, 1, 0, +}; + +#define M(_X_) ((Bit8u)( (_X_) * 2)) +static const Bit8u FreqCreateTable[16] = { + M(0.5), M(1 ), M(2 ), M(3 ), M(4 ), M(5 ), M(6 ), M(7 ), + M(8 ), M(9 ), M(10), M(10), M(12), M(12), M(15), M(15) +}; +#undef M + +//We're not including the highest attack rate, that gets a special value +static const Bit8u AttackSamplesTable[13] = { + 69, 55, 46, 40, + 35, 29, 23, 20, + 19, 15, 11, 10, + 9 +}; +//On a real opl these values take 8 samples to reach and are based upon larger tables +static const Bit8u EnvelopeIncreaseTable[13] = { + 4, 5, 6, 7, + 8, 10, 12, 14, + 16, 20, 24, 28, + 32, +}; + +#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG ) +static Bit16u ExpTable[ 256 ]; +#endif + +#if ( DBOPL_WAVE == WAVE_HANDLER ) +//PI table used by WAVEHANDLER +static Bit16u SinTable[ 512 ]; +#endif + +#if ( DBOPL_WAVE > WAVE_HANDLER ) +//Layout of the waveform table in 512 entry intervals +//With overlapping waves we reduce the table to half it's size + +// | |//\\|____|WAV7|//__|/\ |____|/\/\| +// |\\//| | |WAV7| | \/| | | +// |06 |0126|17 |7 |3 |4 |4 5 |5 | + +//6 is just 0 shifted and masked + +static Bit16s WaveTable[ 8 * 512 ]; +//Distance into WaveTable the wave starts +static const Bit16u WaveBaseTable[8] = { + 0x000, 0x200, 0x200, 0x800, + 0xa00, 0xc00, 0x100, 0x400, + +}; +//Mask the counter with this +static const Bit16u WaveMaskTable[8] = { + 1023, 1023, 511, 511, + 1023, 1023, 512, 1023, +}; + +//Where to start the counter on at keyon +static const Bit16u WaveStartTable[8] = { + 512, 0, 0, 0, + 0, 512, 512, 256, +}; +#endif + +#if ( DBOPL_WAVE == WAVE_TABLEMUL ) +static Bit16u MulTable[ 384 ]; +#endif + +static Bit8u KslTable[ 8 * 16 ]; +static Bit8u TremoloTable[ TREMOLO_TABLE ]; +//Start of a channel behind the chip struct start +static Bit16u ChanOffsetTable[32]; +//Start of an operator behind the chip struct start +static Bit16u OpOffsetTable[64]; + +//The lower bits are the shift of the operator vibrato value +//The highest bit is right shifted to generate -1 or 0 for negation +//So taking the highest input value of 7 this gives 3, 7, 3, 0, -3, -7, -3, 0 +static const Bit8s VibratoTable[ 8 ] = { + 1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00, + 1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80 +}; + +//Shift strength for the ksl value determined by ksl strength +static const Bit8u KslShiftTable[4] = { + 31,1,2,0 +}; + +//Generate a table index and table shift value using input value from a selected rate +static void EnvelopeSelect( Bit8u val, Bit8u& index, Bit8u& shift ) { + if ( val < 13 * 4 ) { //Rate 0 - 12 + shift = 12 - ( val >> 2 ); + index = val & 3; + } else if ( val < 15 * 4 ) { //rate 13 - 14 + shift = 0; + index = val - 12 * 4; + } else { //rate 15 and up + shift = 0; + index = 12; + } +} + +#if ( DBOPL_WAVE == WAVE_HANDLER ) +/* + Generate the different waveforms out of the sine/exponetial table using handlers +*/ +static inline Bits MakeVolume( Bitu wave, Bitu volume ) { + Bitu total = wave + volume; + Bitu index = total & 0xff; + Bitu sig = ExpTable[ index ]; + Bitu exp = total >> 8; +#if 0 + //Check if we overflow the 31 shift limit + if ( exp >= 32 ) { + LOG_MSG( "WTF %d %d", total, exp ); + } +#endif + return (sig >> exp); +}; + +static Bits DB_FASTCALL WaveForm0( Bitu i, Bitu volume ) { + Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0 + Bitu wave = SinTable[i & 511]; + return (MakeVolume( wave, volume ) ^ neg) - neg; +} +static Bits DB_FASTCALL WaveForm1( Bitu i, Bitu volume ) { + Bit32u wave = SinTable[i & 511]; + wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 ); + return MakeVolume( wave, volume ); +} +static Bits DB_FASTCALL WaveForm2( Bitu i, Bitu volume ) { + Bitu wave = SinTable[i & 511]; + return MakeVolume( wave, volume ); +} +static Bits DB_FASTCALL WaveForm3( Bitu i, Bitu volume ) { + Bitu wave = SinTable[i & 255]; + wave |= ( ( (i ^ 256 ) & 256) - 1) >> ( 32 - 12 ); + return MakeVolume( wave, volume ); +} +static Bits DB_FASTCALL WaveForm4( Bitu i, Bitu volume ) { + //Twice as fast + i <<= 1; + Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0 + Bitu wave = SinTable[i & 511]; + wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 ); + return (MakeVolume( wave, volume ) ^ neg) - neg; +} +static Bits DB_FASTCALL WaveForm5( Bitu i, Bitu volume ) { + //Twice as fast + i <<= 1; + Bitu wave = SinTable[i & 511]; + wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 ); + return MakeVolume( wave, volume ); +} +static Bits DB_FASTCALL WaveForm6( Bitu i, Bitu volume ) { + Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0 + return (MakeVolume( 0, volume ) ^ neg) - neg; +} +static Bits DB_FASTCALL WaveForm7( Bitu i, Bitu volume ) { + //Negative is reversed here + Bits neg = (( i >> 9) & 1) - 1; + Bitu wave = (i << 3); + //When negative the volume also runs backwards + wave = ((wave ^ neg) - neg) & 4095; + return (MakeVolume( wave, volume ) ^ neg) - neg; +} + +static const WaveHandler WaveHandlerTable[8] = { + WaveForm0, WaveForm1, WaveForm2, WaveForm3, + WaveForm4, WaveForm5, WaveForm6, WaveForm7 +}; + +#endif + +/* + Operator +*/ + +//We zero out when rate == 0 +inline void Operator::UpdateAttack( const Chip* chip ) { + Bit8u rate = reg60 >> 4; + if ( rate ) { + Bit8u val = (rate << 2) + ksr; + attackAdd = chip->attackRates[ val ]; + rateZero &= ~(1 << ATTACK); + } else { + attackAdd = 0; + rateZero |= (1 << ATTACK); + } +} +inline void Operator::UpdateDecay( const Chip* chip ) { + Bit8u rate = reg60 & 0xf; + if ( rate ) { + Bit8u val = (rate << 2) + ksr; + decayAdd = chip->linearRates[ val ]; + rateZero &= ~(1 << DECAY); + } else { + decayAdd = 0; + rateZero |= (1 << DECAY); + } +} +inline void Operator::UpdateRelease( const Chip* chip ) { + Bit8u rate = reg80 & 0xf; + if ( rate ) { + Bit8u val = (rate << 2) + ksr; + releaseAdd = chip->linearRates[ val ]; + rateZero &= ~(1 << RELEASE); + if ( !(reg20 & MASK_SUSTAIN ) ) { + rateZero &= ~( 1 << SUSTAIN ); + } + } else { + rateZero |= (1 << RELEASE); + releaseAdd = 0; + if ( !(reg20 & MASK_SUSTAIN ) ) { + rateZero |= ( 1 << SUSTAIN ); + } + } +} + +inline void Operator::UpdateAttenuation( ) { + Bit8u kslBase = (Bit8u)((chanData >> SHIFT_KSLBASE) & 0xff); + Bit32u tl = reg40 & 0x3f; + Bit8u kslShift = KslShiftTable[ reg40 >> 6 ]; + //Make sure the attenuation goes to the right bits + totalLevel = tl << ( ENV_BITS - 7 ); //Total level goes 2 bits below max + totalLevel += ( kslBase << ENV_EXTRA ) >> kslShift; +} + +void Operator::UpdateFrequency( ) { + Bit32u freq = chanData & (( 1 << 10 ) - 1); + Bit32u block = (chanData >> 10) & 0xff; +#ifdef WAVE_PRECISION + block = 7 - block; + waveAdd = ( freq * freqMul ) >> block; +#else + waveAdd = ( freq << block ) * freqMul; +#endif + if ( reg20 & MASK_VIBRATO ) { + vibStrength = (Bit8u)(freq >> 7); + +#ifdef WAVE_PRECISION + vibrato = ( vibStrength * freqMul ) >> block; +#else + vibrato = ( vibStrength << block ) * freqMul; +#endif + } else { + vibStrength = 0; + vibrato = 0; + } +} + +void Operator::UpdateRates( const Chip* chip ) { + //Mame seems to reverse this where enabling ksr actually lowers + //the rate, but pdf manuals says otherwise? + Bit8u newKsr = (Bit8u)((chanData >> SHIFT_KEYCODE) & 0xff); + if ( !( reg20 & MASK_KSR ) ) { + newKsr >>= 2; + } + if ( ksr == newKsr ) + return; + ksr = newKsr; + UpdateAttack( chip ); + UpdateDecay( chip ); + UpdateRelease( chip ); +} + +INLINE Bit32s Operator::RateForward( Bit32u add ) { + rateIndex += add; + Bit32s ret = rateIndex >> RATE_SH; + rateIndex = rateIndex & RATE_MASK; + return ret; +} + +template< Operator::State yes> +Bits Operator::TemplateVolume( ) { + Bit32s vol = volume; + Bit32s change; + switch ( yes ) { + case OFF: + return ENV_MAX; + case ATTACK: + change = RateForward( attackAdd ); + if ( !change ) + return vol; + vol += ( (~vol) * change ) >> 3; + if ( vol < ENV_MIN ) { + volume = ENV_MIN; + rateIndex = 0; + SetState( DECAY ); + return ENV_MIN; + } + break; + case DECAY: + vol += RateForward( decayAdd ); + if ( GCC_UNLIKELY(vol >= sustainLevel) ) { + //Check if we didn't overshoot max attenuation, then just go off + if ( GCC_UNLIKELY(vol >= ENV_MAX) ) { + volume = ENV_MAX; + SetState( OFF ); + return ENV_MAX; + } + //Continue as sustain + rateIndex = 0; + SetState( SUSTAIN ); + } + break; + case SUSTAIN: + if ( reg20 & MASK_SUSTAIN ) { + return vol; + } + //In sustain phase, but not sustaining, do regular release + case RELEASE: + vol += RateForward( releaseAdd );; + if ( GCC_UNLIKELY(vol >= ENV_MAX) ) { + volume = ENV_MAX; + SetState( OFF ); + return ENV_MAX; + } + break; + } + volume = vol; + return vol; +} + +static const VolumeHandler VolumeHandlerTable[5] = { + &Operator::TemplateVolume< Operator::OFF >, + &Operator::TemplateVolume< Operator::RELEASE >, + &Operator::TemplateVolume< Operator::SUSTAIN >, + &Operator::TemplateVolume< Operator::DECAY >, + &Operator::TemplateVolume< Operator::ATTACK > +}; + +INLINE Bitu Operator::ForwardVolume() { + return currentLevel + (this->*volHandler)(); +} + + +INLINE Bitu Operator::ForwardWave() { + waveIndex += waveCurrent; + return waveIndex >> WAVE_SH; +} + +void Operator::Write20( const Chip* chip, Bit8u val ) { + Bit8u change = (reg20 ^ val ); + if ( !change ) + return; + reg20 = val; + //Shift the tremolo bit over the entire register, saved a branch, YES! + tremoloMask = (Bit8s)(val) >> 7; + tremoloMask &= ~(( 1 << ENV_EXTRA ) -1); + //Update specific features based on changes + if ( change & MASK_KSR ) { + UpdateRates( chip ); + } + //With sustain enable the volume doesn't change + if ( reg20 & MASK_SUSTAIN || ( !releaseAdd ) ) { + rateZero |= ( 1 << SUSTAIN ); + } else { + rateZero &= ~( 1 << SUSTAIN ); + } + //Frequency multiplier or vibrato changed + if ( change & (0xf | MASK_VIBRATO) ) { + freqMul = chip->freqMul[ val & 0xf ]; + UpdateFrequency(); + } +} + +void Operator::Write40( const Chip* /*chip*/, Bit8u val ) { + if (!(reg40 ^ val )) + return; + reg40 = val; + UpdateAttenuation( ); +} + +void Operator::Write60( const Chip* chip, Bit8u val ) { + Bit8u change = reg60 ^ val; + reg60 = val; + if ( change & 0x0f ) { + UpdateDecay( chip ); + } + if ( change & 0xf0 ) { + UpdateAttack( chip ); + } +} + +void Operator::Write80( const Chip* chip, Bit8u val ) { + Bit8u change = (reg80 ^ val ); + if ( !change ) + return; + reg80 = val; + Bit8u sustain = val >> 4; + //Turn 0xf into 0x1f + sustain |= ( sustain + 1) & 0x10; + sustainLevel = sustain << ( ENV_BITS - 5 ); + if ( change & 0x0f ) { + UpdateRelease( chip ); + } +} + +void Operator::WriteE0( const Chip* chip, Bit8u val ) { + if ( !(regE0 ^ val) ) + return; + //in opl3 mode you can always selet 7 waveforms regardless of waveformselect + Bit8u waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) ); + regE0 = val; +#if ( DBOPL_WAVE == WAVE_HANDLER ) + waveHandler = WaveHandlerTable[ waveForm ]; +#else + waveBase = WaveTable + WaveBaseTable[ waveForm ]; + waveStart = WaveStartTable[ waveForm ] << WAVE_SH; + waveMask = WaveMaskTable[ waveForm ]; +#endif +} + +INLINE void Operator::SetState( Bit8u s ) { + state = s; + volHandler = VolumeHandlerTable[ s ]; +} + +INLINE bool Operator::Silent() const { + if ( !ENV_SILENT( totalLevel + volume ) ) + return false; + if ( !(rateZero & ( 1 << state ) ) ) + return false; + return true; +} + +INLINE void Operator::Prepare( const Chip* chip ) { + currentLevel = totalLevel + (chip->tremoloValue & tremoloMask); + waveCurrent = waveAdd; + if ( vibStrength >> chip->vibratoShift ) { + Bit32s add = vibrato >> chip->vibratoShift; + //Sign extend over the shift value + Bit32s neg = chip->vibratoSign; + //Negate the add with -1 or 0 + add = ( add ^ neg ) - neg; + waveCurrent += add; + } +} + +void Operator::KeyOn( Bit8u mask ) { + if ( !keyOn ) { + //Restart the frequency generator +#if ( DBOPL_WAVE > WAVE_HANDLER ) + waveIndex = waveStart; +#else + waveIndex = 0; +#endif + rateIndex = 0; + SetState( ATTACK ); + } + keyOn |= mask; +} + +void Operator::KeyOff( Bit8u mask ) { + keyOn &= ~mask; + if ( !keyOn ) { + if ( state != OFF ) { + SetState( RELEASE ); + } + } +} + +INLINE Bits Operator::GetWave( Bitu index, Bitu vol ) { +#if ( DBOPL_WAVE == WAVE_HANDLER ) + return waveHandler( index, vol << ( 3 - ENV_EXTRA ) ); +#elif ( DBOPL_WAVE == WAVE_TABLEMUL ) + return (waveBase[ index & waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH; +#elif ( DBOPL_WAVE == WAVE_TABLELOG ) + Bit32s wave = waveBase[ index & waveMask ]; + Bit32u total = ( wave & 0x7fff ) + vol << ( 3 - ENV_EXTRA ); + Bit32s sig = ExpTable[ total & 0xff ]; + Bit32u exp = total >> 8; + Bit32s neg = wave >> 16; + return ((sig ^ neg) - neg) >> exp; +#else +#error "No valid wave routine" +#endif +} + +Bits INLINE Operator::GetSample( Bits modulation ) { + Bitu vol = ForwardVolume(); + if ( ENV_SILENT( vol ) ) { + //Simply forward the wave + waveIndex += waveCurrent; + return 0; + } else { + Bitu index = ForwardWave(); + index += modulation; + return GetWave( index, vol ); + } +} + +Operator::Operator() { + chanData = 0; + freqMul = 0; + waveIndex = 0; + waveAdd = 0; + waveCurrent = 0; + keyOn = 0; + ksr = 0; + reg20 = 0; + reg40 = 0; + reg60 = 0; + reg80 = 0; + regE0 = 0; + SetState( OFF ); + rateZero = (1 << OFF); + sustainLevel = ENV_MAX; + currentLevel = ENV_MAX; + totalLevel = ENV_MAX; + volume = ENV_MAX; + releaseAdd = 0; +} + +/* + Channel +*/ + +Channel::Channel() { + old[0] = old[1] = 0; + chanData = 0; + regB0 = 0; + regC0 = 0; + maskLeft = -1; + maskRight = -1; + feedback = 31; + fourMask = 0; + synthHandler = &Channel::BlockTemplate< sm2FM >; +} + +void Channel::SetChanData( const Chip* chip, Bit32u data ) { + Bit32u change = chanData ^ data; + chanData = data; + Op( 0 )->chanData = data; + Op( 1 )->chanData = data; + //Since a frequency update triggered this, always update frequency + Op( 0 )->UpdateFrequency(); + Op( 1 )->UpdateFrequency(); + if ( change & ( 0xff << SHIFT_KSLBASE ) ) { + Op( 0 )->UpdateAttenuation(); + Op( 1 )->UpdateAttenuation(); + } + if ( change & ( 0xff << SHIFT_KEYCODE ) ) { + Op( 0 )->UpdateRates( chip ); + Op( 1 )->UpdateRates( chip ); + } +} + +void Channel::UpdateFrequency( const Chip* chip, Bit8u fourOp ) { + //Extrace the frequency bits + Bit32u data = chanData & 0xffff; + Bit32u kslBase = KslTable[ data >> 6 ]; + Bit32u keyCode = ( data & 0x1c00) >> 9; + if ( chip->reg08 & 0x40 ) { + keyCode |= ( data & 0x100)>>8; /* notesel == 1 */ + } else { + keyCode |= ( data & 0x200)>>9; /* notesel == 0 */ + } + //Add the keycode and ksl into the highest bits of chanData + data |= (keyCode << SHIFT_KEYCODE) | ( kslBase << SHIFT_KSLBASE ); + ( this + 0 )->SetChanData( chip, data ); + if ( fourOp & 0x3f ) { + ( this + 1 )->SetChanData( chip, data ); + } +} + +void Channel::WriteA0( const Chip* chip, Bit8u val ) { + Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask; + //Don't handle writes to silent fourop channels + if ( fourOp > 0x80 ) + return; + Bit32u change = (chanData ^ val ) & 0xff; + if ( change ) { + chanData ^= change; + UpdateFrequency( chip, fourOp ); + } +} + +void Channel::WriteB0( const Chip* chip, Bit8u val ) { + Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask; + //Don't handle writes to silent fourop channels + if ( fourOp > 0x80 ) + return; + Bitu change = (chanData ^ ( val << 8 ) ) & 0x1f00; + if ( change ) { + chanData ^= change; + UpdateFrequency( chip, fourOp ); + } + //Check for a change in the keyon/off state + if ( !(( val ^ regB0) & 0x20)) + return; + regB0 = val; + if ( val & 0x20 ) { + Op(0)->KeyOn( 0x1 ); + Op(1)->KeyOn( 0x1 ); + if ( fourOp & 0x3f ) { + ( this + 1 )->Op(0)->KeyOn( 1 ); + ( this + 1 )->Op(1)->KeyOn( 1 ); + } + } else { + Op(0)->KeyOff( 0x1 ); + Op(1)->KeyOff( 0x1 ); + if ( fourOp & 0x3f ) { + ( this + 1 )->Op(0)->KeyOff( 1 ); + ( this + 1 )->Op(1)->KeyOff( 1 ); + } + } +} + +void Channel::WriteC0(const Chip* chip, Bit8u val) { + Bit8u change = val ^ regC0; + if (!change) + return; + regC0 = val; + feedback = (regC0 >> 1) & 7; + if (feedback) { + //We shift the input to the right 10 bit wave index value + feedback = 9 - feedback; + } + else { + feedback = 31; + } + UpdateSynth(chip); +} + +void Channel::UpdateSynth( const Chip* chip ) { + //Select the new synth mode + if ( chip->opl3Active ) { + //4-op mode enabled for this channel + if ( (chip->reg104 & fourMask) & 0x3f ) { + Channel* chan0, *chan1; + //Check if it's the 2nd channel in a 4-op + if ( !(fourMask & 0x80 ) ) { + chan0 = this; + chan1 = this + 1; + } else { + chan0 = this - 1; + chan1 = this; + } + + Bit8u synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 ); + switch ( synth ) { + case 0: + chan0->synthHandler = &Channel::BlockTemplate< sm3FMFM >; + break; + case 1: + chan0->synthHandler = &Channel::BlockTemplate< sm3AMFM >; + break; + case 2: + chan0->synthHandler = &Channel::BlockTemplate< sm3FMAM >; + break; + case 3: + chan0->synthHandler = &Channel::BlockTemplate< sm3AMAM >; + break; + } + //Disable updating percussion channels + } else if ((fourMask & 0x40) && ( chip->regBD & 0x20) ) { + + //Regular dual op, am or fm + } else if (regC0 & 1 ) { + synthHandler = &Channel::BlockTemplate< sm3AM >; + } else { + synthHandler = &Channel::BlockTemplate< sm3FM >; + } + maskLeft = (regC0 & 0x10 ) ? -1 : 0; + maskRight = (regC0 & 0x20 ) ? -1 : 0; + //opl2 active + } else { + //Disable updating percussion channels + if ( (fourMask & 0x40) && ( chip->regBD & 0x20 ) ) { + + //Regular dual op, am or fm + } else if (regC0 & 1 ) { + synthHandler = &Channel::BlockTemplate< sm2AM >; + } else { + synthHandler = &Channel::BlockTemplate< sm2FM >; + } + } +} + +template< bool opl3Mode> +INLINE void Channel::GeneratePercussion( Chip* chip, Bit32s* output ) { + Channel* chan = this; + + //BassDrum + Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback; + old[0] = old[1]; + old[1] = static_cast(Op(0)->GetSample( mod )); + + //When bassdrum is in AM mode first operator is ignoed + if ( chan->regC0 & 1 ) { + mod = 0; + } else { + mod = old[0]; + } + Bit32s sample = static_cast(Op(1)->GetSample( mod )); + + + //Precalculate stuff used by other outputs + Bit32u noiseBit = chip->ForwardNoise() & 0x1; + Bit32u c2 = static_cast(Op(2)->ForwardWave()); + Bit32u c5 = static_cast(Op(5)->ForwardWave()); + Bit32u phaseBit = (((c2 & 0x88) ^ ((c2<<5) & 0x80)) | ((c5 ^ (c5<<2)) & 0x20)) ? 0x02 : 0x00; + + //Hi-Hat + Bit32u hhVol = static_cast(Op(2)->ForwardVolume()); + if ( !ENV_SILENT( hhVol ) ) { + Bit32u hhIndex = (phaseBit<<8) | (0x34 << ( phaseBit ^ (noiseBit << 1 ))); + sample += static_cast(Op(2)->GetWave( hhIndex, hhVol )); + } + //Snare Drum + Bit32u sdVol = static_cast(Op(3)->ForwardVolume()); + if ( !ENV_SILENT( sdVol ) ) { + Bit32u sdIndex = ( 0x100 + (c2 & 0x100) ) ^ ( noiseBit << 8 ); + sample += static_cast(Op(3)->GetWave( sdIndex, sdVol )); + } + //Tom-tom + sample += static_cast(Op(4)->GetSample( 0 )); + + //Top-Cymbal + Bit32u tcVol = static_cast(Op(5)->ForwardVolume()); + if ( !ENV_SILENT( tcVol ) ) { + Bit32u tcIndex = (1 + phaseBit) << 8; + sample += static_cast(Op(5)->GetWave( tcIndex, tcVol )); + } + sample <<= 1; + if ( opl3Mode ) { + output[0] += sample; + output[1] += sample; + } else { + output[0] += sample; + } +} + +template +Channel* Channel::BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output ) { + switch( mode ) { + case sm2AM: + case sm3AM: + if ( Op(0)->Silent() && Op(1)->Silent() ) { + old[0] = old[1] = 0; + return (this + 1); + } + break; + case sm2FM: + case sm3FM: + if ( Op(1)->Silent() ) { + old[0] = old[1] = 0; + return (this + 1); + } + break; + case sm3FMFM: + if ( Op(3)->Silent() ) { + old[0] = old[1] = 0; + return (this + 2); + } + break; + case sm3AMFM: + if ( Op(0)->Silent() && Op(3)->Silent() ) { + old[0] = old[1] = 0; + return (this + 2); + } + break; + case sm3FMAM: + if ( Op(1)->Silent() && Op(3)->Silent() ) { + old[0] = old[1] = 0; + return (this + 2); + } + break; + case sm3AMAM: + if ( Op(0)->Silent() && Op(2)->Silent() && Op(3)->Silent() ) { + old[0] = old[1] = 0; + return (this + 2); + } + break; + default: + break; + } + //Init the operators with the the current vibrato and tremolo values + Op( 0 )->Prepare( chip ); + Op( 1 )->Prepare( chip ); + if ( mode > sm4Start ) { + Op( 2 )->Prepare( chip ); + Op( 3 )->Prepare( chip ); + } + if ( mode > sm6Start ) { + Op( 4 )->Prepare( chip ); + Op( 5 )->Prepare( chip ); + } + for ( Bitu i = 0; i < samples; i++ ) { + //Early out for percussion handlers + if ( mode == sm2Percussion ) { + GeneratePercussion( chip, output + i ); + continue; //Prevent some unitialized value bitching + } else if ( mode == sm3Percussion ) { + GeneratePercussion( chip, output + i * 2 ); + continue; //Prevent some unitialized value bitching + } + + //Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise + Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback; + old[0] = old[1]; + old[1] = static_cast(Op(0)->GetSample( mod )); + Bit32s sample; + Bit32s out0 = old[0]; + if ( mode == sm2AM || mode == sm3AM ) { + sample = static_cast(out0 + Op(1)->GetSample( 0 )); + } else if ( mode == sm2FM || mode == sm3FM ) { + sample = static_cast(Op(1)->GetSample( out0 )); + } else if ( mode == sm3FMFM ) { + Bits next = Op(1)->GetSample( out0 ); + next = Op(2)->GetSample( next ); + sample = static_cast(Op(3)->GetSample( next )); + } else if ( mode == sm3AMFM ) { + sample = out0; + Bits next = Op(1)->GetSample( 0 ); + next = Op(2)->GetSample( next ); + sample += static_cast(Op(3)->GetSample( next )); + } else if ( mode == sm3FMAM ) { + sample = static_cast(Op(1)->GetSample( out0 )); + Bits next = Op(2)->GetSample( 0 ); + sample += static_cast(Op(3)->GetSample( next )); + } else if ( mode == sm3AMAM ) { + sample = out0; + Bits next = Op(1)->GetSample( 0 ); + sample += static_cast(Op(2)->GetSample( next )); + sample += static_cast(Op(3)->GetSample( 0 )); + } + switch( mode ) { + case sm2AM: + case sm2FM: + output[ i ] += sample; + break; + case sm3AM: + case sm3FM: + case sm3FMFM: + case sm3AMFM: + case sm3FMAM: + case sm3AMAM: + output[ i * 2 + 0 ] += sample & maskLeft; + output[ i * 2 + 1 ] += sample & maskRight; + break; + default: + break; + } + } + switch( mode ) { + case sm2AM: + case sm2FM: + case sm3AM: + case sm3FM: + return ( this + 1 ); + case sm3FMFM: + case sm3AMFM: + case sm3FMAM: + case sm3AMAM: + return( this + 2 ); + case sm2Percussion: + case sm3Percussion: + return( this + 3 ); + } + return 0; +} + +/* + Chip +*/ + +Chip::Chip() { + reg08 = 0; + reg04 = 0; + regBD = 0; + reg104 = 0; + opl3Active = 0; +} + +INLINE Bit32u Chip::ForwardNoise() { + noiseCounter += noiseAdd; + Bitu count = noiseCounter >> LFO_SH; + noiseCounter &= WAVE_MASK; + for ( ; count > 0; --count ) { + //Noise calculation from mame + noiseValue ^= ( 0x800302 ) & ( 0 - (noiseValue & 1 ) ); + noiseValue >>= 1; + } + return noiseValue; +} + +INLINE Bit32u Chip::ForwardLFO( Bit32u samples ) { + //Current vibrato value, runs 4x slower than tremolo + vibratoSign = ( VibratoTable[ vibratoIndex >> 2] ) >> 7; + vibratoShift = ( VibratoTable[ vibratoIndex >> 2] & 7) + vibratoStrength; + tremoloValue = TremoloTable[ tremoloIndex ] >> tremoloStrength; + + //Check hom many samples there can be done before the value changes + Bit32u todo = LFO_MAX - lfoCounter; + Bit32u count = (todo + lfoAdd - 1) / lfoAdd; + if ( count > samples ) { + count = samples; + lfoCounter += count * lfoAdd; + } else { + lfoCounter += count * lfoAdd; + lfoCounter &= (LFO_MAX - 1); + //Maximum of 7 vibrato value * 4 + vibratoIndex = ( vibratoIndex + 1 ) & 31; + //Clip tremolo to the the table size + if ( tremoloIndex + 1 < TREMOLO_TABLE ) + ++tremoloIndex; + else + tremoloIndex = 0; + } + return count; +} + + +void Chip::WriteBD( Bit8u val ) { + Bit8u change = regBD ^ val; + if ( !change ) + return; + regBD = val; + //TODO could do this with shift and xor? + vibratoStrength = (val & 0x40) ? 0x00 : 0x01; + tremoloStrength = (val & 0x80) ? 0x00 : 0x02; + if ( val & 0x20 ) { + //Drum was just enabled, make sure channel 6 has the right synth + if ( change & 0x20 ) { + if ( opl3Active ) { + chan[6].synthHandler = &Channel::BlockTemplate< sm3Percussion >; + } else { + chan[6].synthHandler = &Channel::BlockTemplate< sm2Percussion >; + } + } + //Bass Drum + if ( val & 0x10 ) { + chan[6].op[0].KeyOn( 0x2 ); + chan[6].op[1].KeyOn( 0x2 ); + } else { + chan[6].op[0].KeyOff( 0x2 ); + chan[6].op[1].KeyOff( 0x2 ); + } + //Hi-Hat + if ( val & 0x1 ) { + chan[7].op[0].KeyOn( 0x2 ); + } else { + chan[7].op[0].KeyOff( 0x2 ); + } + //Snare + if ( val & 0x8 ) { + chan[7].op[1].KeyOn( 0x2 ); + } else { + chan[7].op[1].KeyOff( 0x2 ); + } + //Tom-Tom + if ( val & 0x4 ) { + chan[8].op[0].KeyOn( 0x2 ); + } else { + chan[8].op[0].KeyOff( 0x2 ); + } + //Top Cymbal + if ( val & 0x2 ) { + chan[8].op[1].KeyOn( 0x2 ); + } else { + chan[8].op[1].KeyOff( 0x2 ); + } + //Toggle keyoffs when we turn off the percussion + } else if ( change & 0x20 ) { + //Trigger a reset to setup the original synth handler + //This makes it call + chan[6].UpdateSynth( this ); + chan[6].op[0].KeyOff( 0x2 ); + chan[6].op[1].KeyOff( 0x2 ); + chan[7].op[0].KeyOff( 0x2 ); + chan[7].op[1].KeyOff( 0x2 ); + chan[8].op[0].KeyOff( 0x2 ); + chan[8].op[1].KeyOff( 0x2 ); + } +} + + +#define REGOP( _FUNC_ ) \ + index = ( ( reg >> 3) & 0x20 ) | ( reg & 0x1f ); \ + if ( OpOffsetTable[ index ] ) { \ + Operator* regOp = (Operator*)( ((char *)this ) + OpOffsetTable[ index ] ); \ + regOp->_FUNC_( this, val ); \ + } + +#define REGCHAN( _FUNC_ ) \ + index = ( ( reg >> 4) & 0x10 ) | ( reg & 0xf ); \ + if ( ChanOffsetTable[ index ] ) { \ + Channel* regChan = (Channel*)( ((char *)this ) + ChanOffsetTable[ index ] ); \ + regChan->_FUNC_( this, val ); \ + } + +//Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers +void Chip::UpdateSynths() { + for (int i = 0; i < 18; i++) { + chan[i].UpdateSynth(this); + } +} + + +void Chip::WriteReg( Bit32u reg, Bit8u val ) { + Bitu index; + switch ( (reg & 0xf0) >> 4 ) { + case 0x00 >> 4: + if ( reg == 0x01 ) { + waveFormMask = ( val & 0x20 ) ? 0x7 : 0x0; + } else if ( reg == 0x104 ) { + //Only detect changes in lowest 6 bits + if ( !((reg104 ^ val) & 0x3f) ) + return; + //Always keep the highest bit enabled, for checking > 0x80 + reg104 = 0x80 | ( val & 0x3f ); + //Switch synths when changing the 4op combinations + UpdateSynths(); + } else if ( reg == 0x105 ) { + //MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register + if ( !((opl3Active ^ val) & 1 ) ) + return; + opl3Active = ( val & 1 ) ? 0xff : 0; + //Just tupdate the synths now that opl3 most have been enabled + //This isn't how the real card handles it but need to switch to stereo generating handlers + UpdateSynths(); + } else if ( reg == 0x08 ) { + reg08 = val; + } + case 0x10 >> 4: + break; + case 0x20 >> 4: + case 0x30 >> 4: + REGOP( Write20 ); + break; + case 0x40 >> 4: + case 0x50 >> 4: + REGOP( Write40 ); + break; + case 0x60 >> 4: + case 0x70 >> 4: + REGOP( Write60 ); + break; + case 0x80 >> 4: + case 0x90 >> 4: + REGOP( Write80 ); + break; + case 0xa0 >> 4: + REGCHAN( WriteA0 ); + break; + case 0xb0 >> 4: + if ( reg == 0xbd ) { + WriteBD( val ); + } else { + REGCHAN( WriteB0 ); + } + break; + case 0xc0 >> 4: + REGCHAN( WriteC0 ); + case 0xd0 >> 4: + break; + case 0xe0 >> 4: + case 0xf0 >> 4: + REGOP( WriteE0 ); + break; + } +} + + +Bit32u Chip::WriteAddr( Bit32u port, Bit8u val ) { + switch ( port & 3 ) { + case 0: + return val; + case 2: + if ( opl3Active || (val == 0x05) ) + return 0x100 | val; + else + return val; + } + return 0; +} + +void Chip::GenerateBlock2( Bitu total, Bit32s* output ) { + while ( total > 0 ) { + Bit32u samples = ForwardLFO( static_cast(total) ); + memset(output, 0, sizeof(Bit32s) * samples); +// int count = 0; + for( Channel* ch = chan; ch < chan + 9; ) { +// count++; + ch = (ch->*(ch->synthHandler))( this, samples, output ); + } + total -= samples; + output += samples; + } +} + +void Chip::GenerateBlock2_Mix( Bitu total, Bit32s* output ) { + while ( total > 0 ) { + Bit32u samples = ForwardLFO( static_cast(total) ); +// int count = 0; + for( Channel* ch = chan; ch < chan + 9; ) { +// count++; + ch = (ch->*(ch->synthHandler))( this, samples, output ); + } + total -= samples; + output += samples; + } +} + +void Chip::GenerateBlock3( Bitu total, Bit32s* output ) { + while ( total > 0 ) { + Bit32u samples = ForwardLFO( static_cast(total) ); + memset(output, 0, sizeof(Bit32s) * samples *2); +// int count = 0; + for( Channel* ch = chan; ch < chan + 18; ) { +// count++; + ch = (ch->*(ch->synthHandler))( this, samples, output ); + } + total -= samples; + output += samples * 2; + } +} + +void Chip::GenerateBlock3_Mix( Bitu total, Bit32s* output ) { + while ( total > 0 ) { + Bit32u samples = ForwardLFO( static_cast(total) ); +// int count = 0; + for( Channel* ch = chan; ch < chan + 18; ) { +// count++; + ch = (ch->*(ch->synthHandler))( this, samples, output ); + } + total -= samples; + output += samples * 2; + } +} + +void Chip::Setup( Bit32u rate ) { + double original = OPLRATE; +// double original = rate; + double scale = original / (double)rate; + + //Noise counter is run at the same precision as general waves + noiseAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) ); + noiseCounter = 0; + noiseValue = 1; //Make sure it triggers the noise xor the first time + //The low frequency oscillation counter + //Every time his overflows vibrato and tremoloindex are increased + lfoAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) ); + lfoCounter = 0; + vibratoIndex = 0; + tremoloIndex = 0; + + //With higher octave this gets shifted up + //-1 since the freqCreateTable = *2 +#ifdef WAVE_PRECISION + double freqScale = ( 1 << 7 ) * scale * ( 1 << ( WAVE_SH - 1 - 10)); + for ( int i = 0; i < 16; i++ ) { + freqMul[i] = (Bit32u)( 0.5 + freqScale * FreqCreateTable[ i ] ); + } +#else + Bit32u freqScale = (Bit32u)( 0.5 + scale * ( 1 << ( WAVE_SH - 1 - 10))); + for ( int i = 0; i < 16; i++ ) { + freqMul[i] = freqScale * FreqCreateTable[ i ]; + } +#endif + + //-3 since the real envelope takes 8 steps to reach the single value we supply + for ( Bit8u i = 0; i < 76; i++ ) { + Bit8u index, shift; + EnvelopeSelect( i, index, shift ); + linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 ))); + } +// Bit32s attackDiffs[62]; + //Generate the best matching attack rate + for ( Bit8u i = 0; i < 62; i++ ) { + Bit8u index, shift; + EnvelopeSelect( i, index, shift ); + //Original amount of samples the attack would take + Bit32s original = (Bit32u)( (AttackSamplesTable[ index ] << shift) / scale); + + Bit32s guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 ))); + Bit32s bestAdd = guessAdd; + Bit32u bestDiff = 1 << 30; + for( Bit32u passes = 0; passes < 16; passes ++ ) { + Bit32s volume = ENV_MAX; + Bit32s samples = 0; + Bit32u count = 0; + while ( volume > 0 && samples < original * 2 ) { + count += guessAdd; + Bit32s change = count >> RATE_SH; + count &= RATE_MASK; + if ( GCC_UNLIKELY(change) ) { // less than 1 % + volume += ( ~volume * change ) >> 3; + } + samples++; + + } + Bit32s diff = original - samples; + Bit32u lDiff = labs( diff ); + //Init last on first pass + if ( lDiff < bestDiff ) { + bestDiff = lDiff; + bestAdd = guessAdd; + //We hit an exactly matching sample count + if ( !bestDiff ) + break; + } + //Linear correction factor, not exactly perfect but seems to work + double correct = (original - diff) / (double)original; + guessAdd = (Bit32u)(guessAdd * correct); + //Below our target + if ( diff < 0 ) { + //Always add one here for rounding, an overshoot will get corrected by another pass decreasing + guessAdd++; + } + } + attackRates[i] = bestAdd; + //Keep track of the diffs for some debugging +// attackDiffs[i] = bestDiff; + } + for ( Bit8u i = 62; i < 76; i++ ) { + //This should provide instant volume maximizing + attackRates[i] = 8 << RATE_SH; + } + //Setup the channels with the correct four op flags + //Channels are accessed through a table so they appear linear here + chan[ 0].fourMask = 0x00 | ( 1 << 0 ); + chan[ 1].fourMask = 0x80 | ( 1 << 0 ); + chan[ 2].fourMask = 0x00 | ( 1 << 1 ); + chan[ 3].fourMask = 0x80 | ( 1 << 1 ); + chan[ 4].fourMask = 0x00 | ( 1 << 2 ); + chan[ 5].fourMask = 0x80 | ( 1 << 2 ); + + chan[ 9].fourMask = 0x00 | ( 1 << 3 ); + chan[10].fourMask = 0x80 | ( 1 << 3 ); + chan[11].fourMask = 0x00 | ( 1 << 4 ); + chan[12].fourMask = 0x80 | ( 1 << 4 ); + chan[13].fourMask = 0x00 | ( 1 << 5 ); + chan[14].fourMask = 0x80 | ( 1 << 5 ); + + //mark the percussion channels + chan[ 6].fourMask = 0x40; + chan[ 7].fourMask = 0x40; + chan[ 8].fourMask = 0x40; + + //Clear Everything in opl3 mode + WriteReg( 0x105, 0x1 ); + for ( int i = 0; i < 512; i++ ) { + if ( i == 0x105 ) + continue; + WriteReg( i, 0xff ); + WriteReg( i, 0x0 ); + } + WriteReg( 0x105, 0x0 ); + //Clear everything in opl2 mode + for ( int i = 0; i < 255; i++ ) { + WriteReg( i, 0xff ); + WriteReg( i, 0x0 ); + } +} + +static bool doneTables = false; +void InitTables( void ) { + if ( doneTables ) + return; + doneTables = true; +#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG ) + //Exponential volume table, same as the real adlib + for ( int i = 0; i < 256; i++ ) { + //Save them in reverse + ExpTable[i] = (int)( 0.5 + ( pow(2.0, ( 255 - i) * ( 1.0 /256 ) )-1) * 1024 ); + ExpTable[i] += 1024; //or remove the -1 oh well :) + //Preshift to the left once so the final volume can shift to the right + ExpTable[i] *= 2; + } +#endif +#if ( DBOPL_WAVE == WAVE_HANDLER ) + //Add 0.5 for the trunc rounding of the integer cast + //Do a PI sinetable instead of the original 0.5 PI + for ( int i = 0; i < 512; i++ ) { + SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 ); + } +#endif +#if ( DBOPL_WAVE == WAVE_TABLEMUL ) + //Multiplication based tables + for ( int i = 0; i < 384; i++ ) { + int s = i * 8; + //TODO maybe keep some of the precision errors of the original table? + double val = ( 0.5 + ( pow(2.0, -1.0 + ( 255 - s) * ( 1.0 /256 ) )) * ( 1 << MUL_SH )); + MulTable[i] = (Bit16u)(val); + } + + //Sine Wave Base + for ( int i = 0; i < 512; i++ ) { + WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084); + WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ]; + } + //Exponential wave + for ( int i = 0; i < 256; i++ ) { + WaveTable[ 0x700 + i ] = (Bit16s)( 0.5 + ( pow(2.0, -1.0 + ( 255 - i * 8) * ( 1.0 /256 ) ) ) * 4085 ); + WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ]; + } +#endif +#if ( DBOPL_WAVE == WAVE_TABLELOG ) + //Sine Wave Base + for ( int i = 0; i < 512; i++ ) { + WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 ); + WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i]; + } + //Exponential wave + for ( int i = 0; i < 256; i++ ) { + WaveTable[ 0x700 + i ] = i * 8; + WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8; + } +#endif + + // | |//\\|____|WAV7|//__|/\ |____|/\/\| + // |\\//| | |WAV7| | \/| | | + // |06 |0126|27 |7 |3 |4 |4 5 |5 | + +#if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL )) + for ( int i = 0; i < 256; i++ ) { + //Fill silence gaps + WaveTable[ 0x400 + i ] = WaveTable[0]; + WaveTable[ 0x500 + i ] = WaveTable[0]; + WaveTable[ 0x900 + i ] = WaveTable[0]; + WaveTable[ 0xc00 + i ] = WaveTable[0]; + WaveTable[ 0xd00 + i ] = WaveTable[0]; + //Replicate sines in other pieces + WaveTable[ 0x800 + i ] = WaveTable[ 0x200 + i ]; + //double speed sines + WaveTable[ 0xa00 + i ] = WaveTable[ 0x200 + i * 2 ]; + WaveTable[ 0xb00 + i ] = WaveTable[ 0x000 + i * 2 ]; + WaveTable[ 0xe00 + i ] = WaveTable[ 0x200 + i * 2 ]; + WaveTable[ 0xf00 + i ] = WaveTable[ 0x200 + i * 2 ]; + } +#endif + + //Create the ksl table + for ( int oct = 0; oct < 8; oct++ ) { + int base = oct * 8; + for ( int i = 0; i < 16; i++ ) { + int val = base - KslCreateTable[i]; + if ( val < 0 ) + val = 0; + //*4 for the final range to match attenuation range + KslTable[ oct * 16 + i ] = val * 4; + } + } + //Create the Tremolo table, just increase and decrease a triangle wave + for ( Bit8u i = 0; i < TREMOLO_TABLE / 2; i++ ) { + Bit8u val = i << ENV_EXTRA; + TremoloTable[i] = val; + TremoloTable[TREMOLO_TABLE - 1 - i] = val; + } + //Create a table with offsets of the channels from the start of the chip + DBOPL::Chip* chip = 0; + for ( Bitu i = 0; i < 32; i++ ) { + Bitu index = i & 0xf; + if ( index >= 9 ) { + ChanOffsetTable[i] = 0; + continue; + } + //Make sure the four op channels follow eachother + if ( index < 6 ) { + index = (index % 3) * 2 + ( index / 3 ); + } + //Add back the bits for highest ones + if ( i >= 16 ) + index += 9; + Bitu blah = reinterpret_cast( &(chip->chan[ index ]) ); + ChanOffsetTable[i] = static_cast(blah); + } + //Same for operators + for ( Bitu i = 0; i < 64; i++ ) { + if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) { + OpOffsetTable[i] = 0; + continue; + } + Bitu chNum = (i / 8) * 3 + (i % 8) % 3; + //Make sure we use 16 and up for the 2nd range to match the chanoffset gap + if ( chNum >= 12 ) + chNum += 16 - 12; + Bitu opNum = ( i % 8 ) / 3; + DBOPL::Channel* chan = 0; + Bitu blah = reinterpret_cast( &(chan->op[opNum]) ); + OpOffsetTable[i] = static_cast(ChanOffsetTable[ chNum ] + blah); + } +#if 0 + //Stupid checks if table's are correct + for ( Bitu i = 0; i < 18; i++ ) { + Bit32u find = (Bit16u)( &(chip->chan[ i ]) ); + for ( Bitu c = 0; c < 32; c++ ) { + if ( ChanOffsetTable[c] == find ) { + find = 0; + break; + } + } + if ( find ) { + find = find; + } + } + for ( Bitu i = 0; i < 36; i++ ) { + Bit32u find = (Bit16u)( &(chip->chan[ i / 2 ].op[i % 2]) ); + for ( Bitu c = 0; c < 64; c++ ) { + if ( OpOffsetTable[c] == find ) { + find = 0; + break; + } + } + if ( find ) { + find = find; + } + } +#endif +} + +Bit32u Handler::WriteAddr( Bit32u port, Bit8u val ) { + return chip.WriteAddr( port, val ); + +} +void Handler::WriteReg( Bit32u addr, Bit8u val ) { + chip.WriteReg( addr, val ); +} + +#define DB_MAX(x, y) ((x) > (y) ? (x) : (y)) +#define DB_MIN(x, y) ((x) < (y) ? (x) : (y)) + +#define DBOPL_CLAMP(V, MIN, MAX) DB_MAX(DB_MIN(V, (MAX)), (MIN)) + +void Handler::GenerateArr(Bit32s *out, Bitu *samples) +{ + if(GCC_UNLIKELY(*samples > 512)) + *samples = 512; + if(!chip.opl3Active) + chip.GenerateBlock2(*samples, out); + else + chip.GenerateBlock3(*samples, out); +} + +void Handler::GenerateArr(Bit16s *out, Bitu *samples) +{ + Bit32s out32[1024]; + if(GCC_UNLIKELY(*samples > 512)) + *samples = 512; + memset(out32, 0, sizeof(Bit32s) * 1024); + if(!chip.opl3Active) + chip.GenerateBlock2(*samples, out32); + else + chip.GenerateBlock3(*samples, out32); + Bitu sz = *samples * 2; + for(Bitu i = 0; i < sz; i++) + out[i] = static_cast(DBOPL_CLAMP(out32[i], INT16_MIN, INT16_MAX)); +} + +void Handler::GenerateArrMix(Bit32s *out, Bitu *samples) +{ + if(GCC_UNLIKELY(*samples > 512)) + *samples = 512; + if(!chip.opl3Active) + chip.GenerateBlock2_Mix(*samples, out); + else + chip.GenerateBlock3_Mix(*samples, out); +} + +void Handler::GenerateArrMix(Bit16s *out, Bitu *samples) +{ + Bit32s out32[1024]; + if(GCC_UNLIKELY(*samples > 512)) + *samples = 512; + memset(out32, 0, sizeof(Bit32s) * 1024); + if(!chip.opl3Active) + chip.GenerateBlock2(*samples, out32); + else + chip.GenerateBlock3(*samples, out32); + Bitu sz = *samples * 2; + for(Bitu i = 0; i < sz; i++) + out[i] += static_cast(DBOPL_CLAMP(out32[i], INT16_MIN, INT16_MAX)); +} + +void Handler::Init( Bitu rate ) { + InitTables(); + chip.Setup( static_cast(rate) ); +} + + +} //Namespace DBOPL diff --git a/src/sound/adlmidi/chips/dosbox/dbopl.h b/src/sound/adlmidi/chips/dosbox/dbopl.h new file mode 100644 index 000000000..73c0aa9a1 --- /dev/null +++ b/src/sound/adlmidi/chips/dosbox/dbopl.h @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2002-2018 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#if defined(__GNUC__) && defined(__i386__) +#define DB_FASTCALL __attribute__((fastcall)) +#elif defined(_MSC_VER) +#define DB_FASTCALL __fastcall +#else +#define DB_FASTCALL +#endif + +typedef uintptr_t Bitu; +typedef intptr_t Bits; +typedef uint64_t Bit64u; +typedef int64_t Bit64s; +typedef uint32_t Bit32u; +typedef int32_t Bit32s; +typedef uint16_t Bit16u; +typedef int16_t Bit16s; +typedef uint8_t Bit8u; +typedef int8_t Bit8s; + +//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume +#define WAVE_HANDLER 10 +//Use a logarithmic wavetable with an exponential table for volume +#define WAVE_TABLELOG 11 +//Use a linear wavetable with a multiply table for volume +#define WAVE_TABLEMUL 12 + +//Select the type of wave generator routine +#define DBOPL_WAVE WAVE_TABLEMUL + +namespace DBOPL { + +struct Chip; +struct Operator; +struct Channel; + +#if (DBOPL_WAVE == WAVE_HANDLER) +typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume ); +#endif + +typedef Bits ( DBOPL::Operator::*VolumeHandler) ( ); +typedef Channel* ( DBOPL::Channel::*SynthHandler) ( Chip* chip, Bit32u samples, Bit32s* output ); + +//Different synth modes that can generate blocks of data +typedef enum { + sm2AM, + sm2FM, + sm3AM, + sm3FM, + sm4Start, + sm3FMFM, + sm3AMFM, + sm3FMAM, + sm3AMAM, + sm6Start, + sm2Percussion, + sm3Percussion, +} SynthMode; + +//Shifts for the values contained in chandata variable +enum { + SHIFT_KSLBASE = 16, + SHIFT_KEYCODE = 24, +}; + +struct Operator { +public: + //Masks for operator 20 values + enum { + MASK_KSR = 0x10, + MASK_SUSTAIN = 0x20, + MASK_VIBRATO = 0x40, + MASK_TREMOLO = 0x80, + }; + + typedef enum { + OFF, + RELEASE, + SUSTAIN, + DECAY, + ATTACK, + } State; + + VolumeHandler volHandler; + +#if (DBOPL_WAVE == WAVE_HANDLER) + WaveHandler waveHandler; //Routine that generate a wave +#else + Bit16s* waveBase; + Bit32u waveMask; + Bit32u waveStart; +#endif + Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index + Bit32u waveAdd; //The base frequency without vibrato + Bit32u waveCurrent; //waveAdd + vibratao + + Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this + Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove? + Bit32u vibrato; //Scaled up vibrato strength + Bit32s sustainLevel; //When stopping at sustain level stop here + Bit32s totalLevel; //totalLevel is added to every generated volume + Bit32u currentLevel; //totalLevel + tremolo + Bit32s volume; //The currently active volume + + Bit32u attackAdd; //Timers for the different states of the envelope + Bit32u decayAdd; + Bit32u releaseAdd; + Bit32u rateIndex; //Current position of the evenlope + + Bit8u rateZero; //Bits for the different states of the envelope having no changes + Bit8u keyOn; //Bitmask of different values that can generate keyon + //Registers, also used to check for changes + Bit8u reg20, reg40, reg60, reg80, regE0; + //Active part of the envelope we're in + Bit8u state; + //0xff when tremolo is enabled + Bit8u tremoloMask; + //Strength of the vibrato + Bit8u vibStrength; + //Keep track of the calculated KSR so we can check for changes + Bit8u ksr; +private: + void SetState( Bit8u s ); + void UpdateAttack( const Chip* chip ); + void UpdateRelease( const Chip* chip ); + void UpdateDecay( const Chip* chip ); +public: + void UpdateAttenuation(); + void UpdateRates( const Chip* chip ); + void UpdateFrequency( ); + + void Write20( const Chip* chip, Bit8u val ); + void Write40( const Chip* chip, Bit8u val ); + void Write60( const Chip* chip, Bit8u val ); + void Write80( const Chip* chip, Bit8u val ); + void WriteE0( const Chip* chip, Bit8u val ); + + bool Silent() const; + void Prepare( const Chip* chip ); + + void KeyOn( Bit8u mask); + void KeyOff( Bit8u mask); + + template< State state> + Bits TemplateVolume( ); + + Bit32s RateForward( Bit32u add ); + Bitu ForwardWave(); + Bitu ForwardVolume(); + + Bits GetSample( Bits modulation ); + Bits GetWave( Bitu index, Bitu vol ); +public: + Operator(); +}; + +struct Channel { + Operator op[2]; + inline Operator* Op( Bitu index ) { + return &( ( this + (index >> 1) )->op[ index & 1 ]); + } + SynthHandler synthHandler; + Bit32u chanData; //Frequency/octave and derived values + Bit32s old[2]; //Old data for feedback + + Bit8u feedback; //Feedback shift + Bit8u regB0; //Register values to check for changes + Bit8u regC0; + //This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel + Bit8u fourMask; + Bit8s maskLeft; //Sign extended values for both channel's panning + Bit8s maskRight; + + //Forward the channel data to the operators of the channel + void SetChanData( const Chip* chip, Bit32u data ); + //Change in the chandata, check for new values and if we have to forward to operators + void UpdateFrequency( const Chip* chip, Bit8u fourOp ); + void UpdateSynth(const Chip* chip); + void WriteA0( const Chip* chip, Bit8u val ); + void WriteB0( const Chip* chip, Bit8u val ); + void WriteC0( const Chip* chip, Bit8u val ); + + //call this for the first channel + template< bool opl3Mode > + void GeneratePercussion( Chip* chip, Bit32s* output ); + + //Generate blocks of data in specific modes + template + Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output ); + Channel(); +}; + +struct Chip { + //This is used as the base counter for vibrato and tremolo + Bit32u lfoCounter; + Bit32u lfoAdd; + + + Bit32u noiseCounter; + Bit32u noiseAdd; + Bit32u noiseValue; + + //Frequency scales for the different multiplications + Bit32u freqMul[16]; + //Rates for decay and release for rate of this chip + Bit32u linearRates[76]; + //Best match attack rates for the rate of this chip + Bit32u attackRates[76]; + + //18 channels with 2 operators each + Channel chan[18]; + + Bit8u reg104; + Bit8u reg08; + Bit8u reg04; + Bit8u regBD; + Bit8u vibratoIndex; + Bit8u tremoloIndex; + Bit8s vibratoSign; + Bit8u vibratoShift; + Bit8u tremoloValue; + Bit8u vibratoStrength; + Bit8u tremoloStrength; + //Mask for allowed wave forms + Bit8u waveFormMask; + //0 or -1 when enabled + Bit8s opl3Active; + + //Return the maximum amount of samples before and LFO change + Bit32u ForwardLFO( Bit32u samples ); + Bit32u ForwardNoise(); + + void WriteBD( Bit8u val ); + void WriteReg(Bit32u reg, Bit8u val ); + + Bit32u WriteAddr( Bit32u port, Bit8u val ); + + void GenerateBlock2( Bitu samples, Bit32s* output ); + void GenerateBlock2_Mix( Bitu samples, Bit32s* output ); + void GenerateBlock3( Bitu samples, Bit32s* output ); + void GenerateBlock3_Mix( Bitu samples, Bit32s* output ); + + //Update the synth handlers in all channels + void UpdateSynths(); + void Generate( Bit32u samples ); + void Setup( Bit32u r ); + + Chip(); +}; + +struct Handler { + DBOPL::Chip chip; + Bit32u WriteAddr( Bit32u port, Bit8u val ); + void WriteReg( Bit32u addr, Bit8u val ); + void GenerateArr(Bit32s *out, Bitu *samples); + void GenerateArr(Bit16s *out, Bitu *samples); + void GenerateArrMix(Bit32s *out, Bitu *samples); + void GenerateArrMix(Bit16s *out, Bitu *samples); + void Init( Bitu rate ); +}; + + +} //Namespace diff --git a/src/sound/adlmidi/chips/dosbox_opl3.cpp b/src/sound/adlmidi/chips/dosbox_opl3.cpp new file mode 100644 index 000000000..30fa38ea5 --- /dev/null +++ b/src/sound/adlmidi/chips/dosbox_opl3.cpp @@ -0,0 +1,54 @@ +#include "dosbox_opl3.h" +#include "dosbox/dbopl.h" +#include +#include +#include + +DosBoxOPL3::DosBoxOPL3() : + OPLChipBaseBufferedT(), + m_chip(new DBOPL::Handler) +{ + reset(); +} + +DosBoxOPL3::~DosBoxOPL3() +{ + DBOPL::Handler *chip_r = reinterpret_cast(m_chip); + delete chip_r; +} + +void DosBoxOPL3::setRate(uint32_t rate) +{ + OPLChipBaseBufferedT::setRate(rate); + DBOPL::Handler *chip_r = reinterpret_cast(m_chip); + chip_r->~Handler(); + new(chip_r) DBOPL::Handler; + chip_r->Init(effectiveRate()); +} + +void DosBoxOPL3::reset() +{ + OPLChipBaseBufferedT::reset(); + DBOPL::Handler *chip_r = reinterpret_cast(m_chip); + chip_r->~Handler(); + new(chip_r) DBOPL::Handler; + chip_r->Init(effectiveRate()); +} + +void DosBoxOPL3::writeReg(uint16_t addr, uint8_t data) +{ + DBOPL::Handler *chip_r = reinterpret_cast(m_chip); + chip_r->WriteReg(static_cast(addr), data); +} + +void DosBoxOPL3::nativeGenerateN(int16_t *output, size_t frames) +{ + DBOPL::Handler *chip_r = reinterpret_cast(m_chip); + Bitu frames_i = frames; + chip_r->GenerateArr(output, &frames_i); +} + +const char *DosBoxOPL3::emulatorName() +{ + return "DosBox 0.74-r4111 OPL3"; +} diff --git a/src/sound/adlmidi/chips/dosbox_opl3.h b/src/sound/adlmidi/chips/dosbox_opl3.h new file mode 100644 index 000000000..192802666 --- /dev/null +++ b/src/sound/adlmidi/chips/dosbox_opl3.h @@ -0,0 +1,23 @@ +#ifndef DOSBOX_OPL3_H +#define DOSBOX_OPL3_H + +#include "opl_chip_base.h" + +class DosBoxOPL3 final : public OPLChipBaseBufferedT +{ + void *m_chip; +public: + DosBoxOPL3(); + ~DosBoxOPL3() override; + + bool canRunAtPcmRate() const override { return true; } + void setRate(uint32_t rate) override; + void reset() override; + void writeReg(uint16_t addr, uint8_t data) override; + void nativePreGenerate() override {} + void nativePostGenerate() override {} + void nativeGenerateN(int16_t *output, size_t frames) override; + const char *emulatorName() override; +}; + +#endif // DOSBOX_OPL3_H diff --git a/src/sound/adlmidi/chips/nuked/nukedopl3.c b/src/sound/adlmidi/chips/nuked/nukedopl3.c new file mode 100644 index 000000000..87d321257 --- /dev/null +++ b/src/sound/adlmidi/chips/nuked/nukedopl3.c @@ -0,0 +1,1391 @@ +/* + * Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * Nuked OPL3 emulator. + * Thanks: + * MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): + * Feedback and Rhythm part calculation information. + * forums.submarine.org.uk(carbon14, opl3): + * Tremolo and phase generator calculation information. + * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): + * OPL2 ROMs. + * siliconpr0n.org(John McMaster, digshadow): + * YMF262 and VRC VII decaps and die shots. + * + * version: 1.8 + */ + +#include +#include +#include +#include "nukedopl3.h" + +#define RSM_FRAC 10 + +/* Channel types */ + +enum { + ch_2op = 0, + ch_4op = 1, + ch_4op2 = 2, + ch_drum = 3 +}; + +/* Envelope key types */ + +enum { + egk_norm = 0x01, + egk_drum = 0x02 +}; + + +/* + * logsin table + */ + +static const Bit16u logsinrom[256] = { + 0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471, + 0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365, + 0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd, + 0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261, + 0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f, + 0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd, + 0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195, + 0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166, + 0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c, + 0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118, + 0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8, + 0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db, + 0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1, + 0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9, + 0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094, + 0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081, + 0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070, + 0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060, + 0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052, + 0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045, + 0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039, + 0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f, + 0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026, + 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e, + 0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017, + 0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011, + 0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c, + 0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007, + 0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004, + 0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002, + 0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 +}; + +/* + * exp table + */ + +static const Bit16u exprom[256] = { + 0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4, + 0x7cf, 0x7c9, 0x7c4, 0x7bf, 0x7b9, 0x7b4, 0x7ae, 0x7a9, + 0x7a4, 0x79f, 0x799, 0x794, 0x78f, 0x78a, 0x784, 0x77f, + 0x77a, 0x775, 0x770, 0x76a, 0x765, 0x760, 0x75b, 0x756, + 0x751, 0x74c, 0x747, 0x742, 0x73d, 0x738, 0x733, 0x72e, + 0x729, 0x724, 0x71f, 0x71a, 0x715, 0x710, 0x70b, 0x706, + 0x702, 0x6fd, 0x6f8, 0x6f3, 0x6ee, 0x6e9, 0x6e5, 0x6e0, + 0x6db, 0x6d6, 0x6d2, 0x6cd, 0x6c8, 0x6c4, 0x6bf, 0x6ba, + 0x6b5, 0x6b1, 0x6ac, 0x6a8, 0x6a3, 0x69e, 0x69a, 0x695, + 0x691, 0x68c, 0x688, 0x683, 0x67f, 0x67a, 0x676, 0x671, + 0x66d, 0x668, 0x664, 0x65f, 0x65b, 0x657, 0x652, 0x64e, + 0x649, 0x645, 0x641, 0x63c, 0x638, 0x634, 0x630, 0x62b, + 0x627, 0x623, 0x61e, 0x61a, 0x616, 0x612, 0x60e, 0x609, + 0x605, 0x601, 0x5fd, 0x5f9, 0x5f5, 0x5f0, 0x5ec, 0x5e8, + 0x5e4, 0x5e0, 0x5dc, 0x5d8, 0x5d4, 0x5d0, 0x5cc, 0x5c8, + 0x5c4, 0x5c0, 0x5bc, 0x5b8, 0x5b4, 0x5b0, 0x5ac, 0x5a8, + 0x5a4, 0x5a0, 0x59c, 0x599, 0x595, 0x591, 0x58d, 0x589, + 0x585, 0x581, 0x57e, 0x57a, 0x576, 0x572, 0x56f, 0x56b, + 0x567, 0x563, 0x560, 0x55c, 0x558, 0x554, 0x551, 0x54d, + 0x549, 0x546, 0x542, 0x53e, 0x53b, 0x537, 0x534, 0x530, + 0x52c, 0x529, 0x525, 0x522, 0x51e, 0x51b, 0x517, 0x514, + 0x510, 0x50c, 0x509, 0x506, 0x502, 0x4ff, 0x4fb, 0x4f8, + 0x4f4, 0x4f1, 0x4ed, 0x4ea, 0x4e7, 0x4e3, 0x4e0, 0x4dc, + 0x4d9, 0x4d6, 0x4d2, 0x4cf, 0x4cc, 0x4c8, 0x4c5, 0x4c2, + 0x4be, 0x4bb, 0x4b8, 0x4b5, 0x4b1, 0x4ae, 0x4ab, 0x4a8, + 0x4a4, 0x4a1, 0x49e, 0x49b, 0x498, 0x494, 0x491, 0x48e, + 0x48b, 0x488, 0x485, 0x482, 0x47e, 0x47b, 0x478, 0x475, + 0x472, 0x46f, 0x46c, 0x469, 0x466, 0x463, 0x460, 0x45d, + 0x45a, 0x457, 0x454, 0x451, 0x44e, 0x44b, 0x448, 0x445, + 0x442, 0x43f, 0x43c, 0x439, 0x436, 0x433, 0x430, 0x42d, + 0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416, + 0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400 +}; + +/* + * freq mult table multiplied by 2 + * + * 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 + */ + +static const Bit8u mt[16] = { + 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30 +}; + +/* + * ksl table + */ + +static const Bit8u kslrom[16] = { + 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64 +}; + +static const Bit8u kslshift[4] = { + 8, 1, 2, 0 +}; + +/* + * envelope generator constants + */ + +static const Bit8u eg_incstep[4][4] = { + { 0, 0, 0, 0 }, + { 1, 0, 0, 0 }, + { 1, 0, 1, 0 }, + { 1, 1, 1, 0 } +}; + +/* + * address decoding + */ + +static const Bit8s ad_slot[0x20] = { + 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1, + 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +static const Bit8u ch_slot[18] = { + 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 +}; + +/* + * Envelope generator + */ + +typedef Bit16s(*envelope_sinfunc)(Bit16u phase, Bit16u envelope); +typedef void(*envelope_genfunc)(opl3_slot *slott); + +static Bit16s OPL3_EnvelopeCalcExp(Bit32u level) +{ + if (level > 0x1fff) + { + level = 0x1fff; + } + return (exprom[level & 0xff] << 1) >> (level >> 8); +} + +static Bit16s OPL3_EnvelopeCalcSin0(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + Bit16u neg = 0; + phase &= 0x3ff; + if (phase & 0x200) + { + neg = 0xffff; + } + if (phase & 0x100) + { + out = logsinrom[(phase & 0xff) ^ 0xff]; + } + else + { + out = logsinrom[phase & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; +} + +static Bit16s OPL3_EnvelopeCalcSin1(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + phase &= 0x3ff; + if (phase & 0x200) + { + out = 0x1000; + } + else if (phase & 0x100) + { + out = logsinrom[(phase & 0xff) ^ 0xff]; + } + else + { + out = logsinrom[phase & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)); +} + +static Bit16s OPL3_EnvelopeCalcSin2(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + phase &= 0x3ff; + if (phase & 0x100) + { + out = logsinrom[(phase & 0xff) ^ 0xff]; + } + else + { + out = logsinrom[phase & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)); +} + +static Bit16s OPL3_EnvelopeCalcSin3(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + phase &= 0x3ff; + if (phase & 0x100) + { + out = 0x1000; + } + else + { + out = logsinrom[phase & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)); +} + +static Bit16s OPL3_EnvelopeCalcSin4(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + Bit16u neg = 0; + phase &= 0x3ff; + if ((phase & 0x300) == 0x100) + { + neg = 0xffff; + } + if (phase & 0x200) + { + out = 0x1000; + } + else if (phase & 0x80) + { + out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; + } + else + { + out = logsinrom[(phase << 1) & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; +} + +static Bit16s OPL3_EnvelopeCalcSin5(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + phase &= 0x3ff; + if (phase & 0x200) + { + out = 0x1000; + } + else if (phase & 0x80) + { + out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; + } + else + { + out = logsinrom[(phase << 1) & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)); +} + +static Bit16s OPL3_EnvelopeCalcSin6(Bit16u phase, Bit16u envelope) +{ + Bit16u neg = 0; + phase &= 0x3ff; + if (phase & 0x200) + { + neg = 0xffff; + } + return OPL3_EnvelopeCalcExp(envelope << 3) ^ neg; +} + +static Bit16s OPL3_EnvelopeCalcSin7(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + Bit16u neg = 0; + phase &= 0x3ff; + if (phase & 0x200) + { + neg = 0xffff; + phase = (phase & 0x1ff) ^ 0x1ff; + } + out = phase << 3; + return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; +} + +static const envelope_sinfunc envelope_sin[8] = { + OPL3_EnvelopeCalcSin0, + OPL3_EnvelopeCalcSin1, + OPL3_EnvelopeCalcSin2, + OPL3_EnvelopeCalcSin3, + OPL3_EnvelopeCalcSin4, + OPL3_EnvelopeCalcSin5, + OPL3_EnvelopeCalcSin6, + OPL3_EnvelopeCalcSin7 +}; + +enum envelope_gen_num +{ + envelope_gen_num_attack = 0, + envelope_gen_num_decay = 1, + envelope_gen_num_sustain = 2, + envelope_gen_num_release = 3 +}; + +static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) +{ + Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2) + - ((0x08 - slot->channel->block) << 5); + if (ksl < 0) + { + ksl = 0; + } + slot->eg_ksl = (Bit8u)ksl; +} + +static void OPL3_EnvelopeCalc(opl3_slot *slot) +{ + Bit8u nonzero; + Bit8u rate; + Bit8u rate_hi; + Bit8u rate_lo; + Bit8u reg_rate = 0; + Bit8u ks; + Bit8u eg_shift, shift; + Bit16u eg_rout; + Bit16s eg_inc; + Bit8u eg_off; + Bit8u reset = 0; + slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) + + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; + if (slot->key && slot->eg_gen == envelope_gen_num_release) + { + reset = 1; + reg_rate = slot->reg_ar; + } + else + { + switch (slot->eg_gen) + { + case envelope_gen_num_attack: + reg_rate = slot->reg_ar; + break; + case envelope_gen_num_decay: + reg_rate = slot->reg_dr; + break; + case envelope_gen_num_sustain: + if (!slot->reg_type) + { + reg_rate = slot->reg_rr; + } + break; + case envelope_gen_num_release: + reg_rate = slot->reg_rr; + break; + } + } + slot->pg_reset = reset; + ks = slot->channel->ksv >> ((slot->reg_ksr ^ 1) << 1); + nonzero = (reg_rate != 0); + rate = ks + (reg_rate << 2); + rate_hi = rate >> 2; + rate_lo = rate & 0x03; + if (rate_hi & 0x10) + { + rate_hi = 0x0f; + } + eg_shift = rate_hi + slot->chip->eg_add; + shift = 0; + if (nonzero) + { + if (rate_hi < 12) + { + if (slot->chip->eg_state) + { + switch (eg_shift) + { + case 12: + shift = 1; + break; + case 13: + shift = (rate_lo >> 1) & 0x01; + break; + case 14: + shift = rate_lo & 0x01; + break; + default: + break; + } + } + } + else + { + shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->chip->timer & 0x03]; + if (shift & 0x04) + { + shift = 0x03; + } + if (!shift) + { + shift = slot->chip->eg_state; + } + } + } + eg_rout = slot->eg_rout; + eg_inc = 0; + eg_off = 0; + /* Instant attack */ + if (reset && rate_hi == 0x0f) + { + eg_rout = 0x00; + } + /* Envelope off */ + if ((slot->eg_rout & 0x1f8) == 0x1f8) + { + eg_off = 1; + } + if (slot->eg_gen != envelope_gen_num_attack && !reset && eg_off) + { + eg_rout = 0x1ff; + } + switch (slot->eg_gen) + { + case envelope_gen_num_attack: + if (!slot->eg_rout) + { + slot->eg_gen = envelope_gen_num_decay; + } + else if (slot->key && shift > 0 && rate_hi != 0x0f) + { + eg_inc = ((~slot->eg_rout) << shift) >> 4; + } + break; + case envelope_gen_num_decay: + if ((slot->eg_rout >> 4) == slot->reg_sl) + { + slot->eg_gen = envelope_gen_num_sustain; + } + else if (!eg_off && !reset && shift > 0) + { + eg_inc = 1 << (shift - 1); + } + break; + case envelope_gen_num_sustain: + case envelope_gen_num_release: + if (!eg_off && !reset && shift > 0) + { + eg_inc = 1 << (shift - 1); + } + break; + } + slot->eg_rout = (eg_rout + eg_inc) & 0x1ff; + /* Key off */ + if (reset) + { + slot->eg_gen = envelope_gen_num_attack; + } + if (!slot->key) + { + slot->eg_gen = envelope_gen_num_release; + } +} + +static void OPL3_EnvelopeKeyOn(opl3_slot *slot, Bit8u type) +{ + slot->key |= type; +} + +static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type) +{ + slot->key &= ~type; +} + +/* + * Phase Generator + */ + +static void OPL3_PhaseGenerate(opl3_slot *slot) +{ + opl3_chip *chip; + Bit16u f_num; + Bit32u basefreq; + Bit8u rm_xor, n_bit; + Bit32u noise; + Bit16u phase; + + chip = slot->chip; + f_num = slot->channel->f_num; + if (slot->reg_vib) + { + Bit8s range; + Bit8u vibpos; + + range = (f_num >> 7) & 7; + vibpos = slot->chip->vibpos; + + if (!(vibpos & 3)) + { + range = 0; + } + else if (vibpos & 1) + { + range >>= 1; + } + range >>= slot->chip->vibshift; + + if (vibpos & 4) + { + range = -range; + } + f_num += range; + } + basefreq = (f_num << slot->channel->block) >> 1; + phase = (Bit16u)(slot->pg_phase >> 9); + if (slot->pg_reset) + { + slot->pg_phase = 0; + } + slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; + /* Rhythm mode */ + noise = chip->noise; + slot->pg_phase_out = phase; + if (slot->slot_num == 13) /* hh */ + { + chip->rm_hh_bit2 = (phase >> 2) & 1; + chip->rm_hh_bit3 = (phase >> 3) & 1; + chip->rm_hh_bit7 = (phase >> 7) & 1; + chip->rm_hh_bit8 = (phase >> 8) & 1; + } + if (slot->slot_num == 17 && (chip->rhy & 0x20)) /* tc */ + { + chip->rm_tc_bit3 = (phase >> 3) & 1; + chip->rm_tc_bit5 = (phase >> 5) & 1; + } + if (chip->rhy & 0x20) + { + rm_xor = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7) + | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5) + | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5); + switch (slot->slot_num) + { + case 13: /* hh */ + slot->pg_phase_out = rm_xor << 9; + if (rm_xor ^ (noise & 1)) + { + slot->pg_phase_out |= 0xd0; + } + else + { + slot->pg_phase_out |= 0x34; + } + break; + case 16: /* sd */ + slot->pg_phase_out = (chip->rm_hh_bit8 << 9) + | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8); + break; + case 17: /* tc */ + slot->pg_phase_out = (rm_xor << 9) | 0x80; + break; + default: + break; + } + } + n_bit = ((noise >> 14) ^ noise) & 0x01; + chip->noise = (noise >> 1) | (n_bit << 22); +} + +/* + * Slot + */ + +static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data) +{ + if ((data >> 7) & 0x01) + { + slot->trem = &slot->chip->tremolo; + } + else + { + slot->trem = (Bit8u*)&slot->chip->zeromod; + } + slot->reg_vib = (data >> 6) & 0x01; + slot->reg_type = (data >> 5) & 0x01; + slot->reg_ksr = (data >> 4) & 0x01; + slot->reg_mult = data & 0x0f; +} + +static void OPL3_SlotWrite40(opl3_slot *slot, Bit8u data) +{ + slot->reg_ksl = (data >> 6) & 0x03; + slot->reg_tl = data & 0x3f; + OPL3_EnvelopeUpdateKSL(slot); +} + +static void OPL3_SlotWrite60(opl3_slot *slot, Bit8u data) +{ + slot->reg_ar = (data >> 4) & 0x0f; + slot->reg_dr = data & 0x0f; +} + +static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data) +{ + slot->reg_sl = (data >> 4) & 0x0f; + if (slot->reg_sl == 0x0f) + { + slot->reg_sl = 0x1f; + } + slot->reg_rr = data & 0x0f; +} + +static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data) +{ + slot->reg_wf = data & 0x07; + if (slot->chip->newm == 0x00) + { + slot->reg_wf &= 0x03; + } +} + +static void OPL3_SlotGenerate(opl3_slot *slot) +{ + slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out); +} + +static void OPL3_SlotCalcFB(opl3_slot *slot) +{ + if (slot->channel->fb != 0x00) + { + slot->fbmod = (slot->prout + slot->out) >> (0x09 - slot->channel->fb); + } + else + { + slot->fbmod = 0; + } + slot->prout = slot->out; +} + +/* + * Channel + */ + +static void OPL3_ChannelSetupAlg(opl3_channel *channel); + +static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) +{ + opl3_channel *channel6; + opl3_channel *channel7; + opl3_channel *channel8; + Bit8u chnum; + + chip->rhy = data & 0x3f; + if (chip->rhy & 0x20) + { + channel6 = &chip->channel[6]; + channel7 = &chip->channel[7]; + channel8 = &chip->channel[8]; + channel6->out[0] = &channel6->slotz[1]->out; + channel6->out[1] = &channel6->slotz[1]->out; + channel6->out[2] = &chip->zeromod; + channel6->out[3] = &chip->zeromod; + channel7->out[0] = &channel7->slotz[0]->out; + channel7->out[1] = &channel7->slotz[0]->out; + channel7->out[2] = &channel7->slotz[1]->out; + channel7->out[3] = &channel7->slotz[1]->out; + channel8->out[0] = &channel8->slotz[0]->out; + channel8->out[1] = &channel8->slotz[0]->out; + channel8->out[2] = &channel8->slotz[1]->out; + channel8->out[3] = &channel8->slotz[1]->out; + for (chnum = 6; chnum < 9; chnum++) + { + chip->channel[chnum].chtype = ch_drum; + } + OPL3_ChannelSetupAlg(channel6); + OPL3_ChannelSetupAlg(channel7); + OPL3_ChannelSetupAlg(channel8); + /* hh */ + if (chip->rhy & 0x01) + { + OPL3_EnvelopeKeyOn(channel7->slotz[0], egk_drum); + } + else + { + OPL3_EnvelopeKeyOff(channel7->slotz[0], egk_drum); + } + /* tc */ + if (chip->rhy & 0x02) + { + OPL3_EnvelopeKeyOn(channel8->slotz[1], egk_drum); + } + else + { + OPL3_EnvelopeKeyOff(channel8->slotz[1], egk_drum); + } + /* tom */ + if (chip->rhy & 0x04) + { + OPL3_EnvelopeKeyOn(channel8->slotz[0], egk_drum); + } + else + { + OPL3_EnvelopeKeyOff(channel8->slotz[0], egk_drum); + } + /* sd */ + if (chip->rhy & 0x08) + { + OPL3_EnvelopeKeyOn(channel7->slotz[1], egk_drum); + } + else + { + OPL3_EnvelopeKeyOff(channel7->slotz[1], egk_drum); + } + /* bd */ + if (chip->rhy & 0x10) + { + OPL3_EnvelopeKeyOn(channel6->slotz[0], egk_drum); + OPL3_EnvelopeKeyOn(channel6->slotz[1], egk_drum); + } + else + { + OPL3_EnvelopeKeyOff(channel6->slotz[0], egk_drum); + OPL3_EnvelopeKeyOff(channel6->slotz[1], egk_drum); + } + } + else + { + for (chnum = 6; chnum < 9; chnum++) + { + chip->channel[chnum].chtype = ch_2op; + OPL3_ChannelSetupAlg(&chip->channel[chnum]); + OPL3_EnvelopeKeyOff(chip->channel[chnum].slotz[0], egk_drum); + OPL3_EnvelopeKeyOff(chip->channel[chnum].slotz[1], egk_drum); + } + } +} + +static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data) +{ + if (channel->chip->newm && channel->chtype == ch_4op2) + { + return; + } + channel->f_num = (channel->f_num & 0x300) | data; + channel->ksv = (channel->block << 1) + | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); + OPL3_EnvelopeUpdateKSL(channel->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->slotz[1]); + if (channel->chip->newm && channel->chtype == ch_4op) + { + channel->pair->f_num = channel->f_num; + channel->pair->ksv = channel->ksv; + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[1]); + } +} + +static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) +{ + if (channel->chip->newm && channel->chtype == ch_4op2) + { + return; + } + channel->f_num = (channel->f_num & 0xff) | ((data & 0x03) << 8); + channel->block = (data >> 2) & 0x07; + channel->ksv = (channel->block << 1) + | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); + OPL3_EnvelopeUpdateKSL(channel->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->slotz[1]); + if (channel->chip->newm && channel->chtype == ch_4op) + { + channel->pair->f_num = channel->f_num; + channel->pair->block = channel->block; + channel->pair->ksv = channel->ksv; + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[1]); + } +} + +static void OPL3_ChannelSetupAlg(opl3_channel *channel) +{ + if (channel->chtype == ch_drum) + { + if (channel->ch_num == 7 || channel->ch_num == 8) + { + channel->slotz[0]->mod = &channel->chip->zeromod; + channel->slotz[1]->mod = &channel->chip->zeromod; + return; + } + switch (channel->alg & 0x01) + { + case 0x00: + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->slotz[0]->out; + break; + case 0x01: + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->chip->zeromod; + break; + } + return; + } + if (channel->alg & 0x08) + { + return; + } + if (channel->alg & 0x04) + { + channel->pair->out[0] = &channel->chip->zeromod; + channel->pair->out[1] = &channel->chip->zeromod; + channel->pair->out[2] = &channel->chip->zeromod; + channel->pair->out[3] = &channel->chip->zeromod; + switch (channel->alg & 0x03) + { + case 0x00: + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->pair->slotz[0]->out; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->slotz[1]->out; + channel->out[1] = &channel->chip->zeromod; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; + break; + case 0x01: + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->pair->slotz[0]->out; + channel->slotz[0]->mod = &channel->chip->zeromod; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->pair->slotz[1]->out; + channel->out[1] = &channel->slotz[1]->out; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; + break; + case 0x02: + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->chip->zeromod; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->pair->slotz[0]->out; + channel->out[1] = &channel->slotz[1]->out; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; + break; + case 0x03: + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->chip->zeromod; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->chip->zeromod; + channel->out[0] = &channel->pair->slotz[0]->out; + channel->out[1] = &channel->slotz[0]->out; + channel->out[2] = &channel->slotz[1]->out; + channel->out[3] = &channel->chip->zeromod; + break; + } + } + else + { + switch (channel->alg & 0x01) + { + case 0x00: + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->slotz[1]->out; + channel->out[1] = &channel->chip->zeromod; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; + break; + case 0x01: + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->chip->zeromod; + channel->out[0] = &channel->slotz[0]->out; + channel->out[1] = &channel->slotz[1]->out; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; + break; + } + } +} + +static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data) +{ + channel->fb = (data & 0x0e) >> 1; + channel->con = data & 0x01; + channel->alg = channel->con; + if (channel->chip->newm) + { + if (channel->chtype == ch_4op) + { + channel->pair->alg = 0x04 | (channel->con << 1) | (channel->pair->con); + channel->alg = 0x08; + OPL3_ChannelSetupAlg(channel->pair); + } + else if (channel->chtype == ch_4op2) + { + channel->alg = 0x04 | (channel->pair->con << 1) | (channel->con); + channel->pair->alg = 0x08; + OPL3_ChannelSetupAlg(channel); + } + else + { + OPL3_ChannelSetupAlg(channel); + } + } + else + { + OPL3_ChannelSetupAlg(channel); + } + if (channel->chip->newm) + { + channel->cha = ((data >> 4) & 0x01) ? ~0 : 0; + channel->chb = ((data >> 5) & 0x01) ? ~0 : 0; + } + else + { + channel->cha = channel->chb = (Bit16u)~0; + } +} + +static void OPL3_ChannelKeyOn(opl3_channel *channel) +{ + if (channel->chip->newm) + { + if (channel->chtype == ch_4op) + { + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->pair->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->pair->slotz[1], egk_norm); + } + else if (channel->chtype == ch_2op || channel->chtype == ch_drum) + { + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); + } + } + else + { + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); + } +} + +static void OPL3_ChannelKeyOff(opl3_channel *channel) +{ + if (channel->chip->newm) + { + if (channel->chtype == ch_4op) + { + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->pair->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->pair->slotz[1], egk_norm); + } + else if (channel->chtype == ch_2op || channel->chtype == ch_drum) + { + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); + } + } + else + { + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); + } +} + +static void OPL3_ChannelSet4Op(opl3_chip *chip, Bit8u data) +{ + Bit8u bit; + Bit8u chnum; + for (bit = 0; bit < 6; bit++) + { + chnum = bit; + if (bit >= 3) + { + chnum += 9 - 3; + } + if ((data >> bit) & 0x01) + { + chip->channel[chnum].chtype = ch_4op; + chip->channel[chnum + 3].chtype = ch_4op2; + } + else + { + chip->channel[chnum].chtype = ch_2op; + chip->channel[chnum + 3].chtype = ch_2op; + } + } +} + +static Bit16s OPL3_ClipSample(Bit32s sample) +{ + if (sample > 32767) + { + sample = 32767; + } + else if (sample < -32768) + { + sample = -32768; + } + return (Bit16s)sample; +} + +void OPL3_Generate(opl3_chip *chip, Bit16s *buf) +{ + Bit8u ii; + Bit8u jj; + Bit16s accm; + Bit8u shift = 0; + + buf[1] = OPL3_ClipSample(chip->mixbuff[1]); + + for (ii = 0; ii < 15; ii++) + { + OPL3_SlotCalcFB(&chip->slot[ii]); + OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); + OPL3_SlotGenerate(&chip->slot[ii]); + } + + chip->mixbuff[0] = 0; + for (ii = 0; ii < 18; ii++) + { + accm = 0; + for (jj = 0; jj < 4; jj++) + { + accm += *chip->channel[ii].out[jj]; + } + chip->mixbuff[0] += (Bit16s)(accm & chip->channel[ii].cha); + } + + for (ii = 15; ii < 18; ii++) + { + OPL3_SlotCalcFB(&chip->slot[ii]); + OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); + OPL3_SlotGenerate(&chip->slot[ii]); + } + + buf[0] = OPL3_ClipSample(chip->mixbuff[0]); + + for (ii = 18; ii < 33; ii++) + { + OPL3_SlotCalcFB(&chip->slot[ii]); + OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); + OPL3_SlotGenerate(&chip->slot[ii]); + } + + chip->mixbuff[1] = 0; + for (ii = 0; ii < 18; ii++) + { + accm = 0; + for (jj = 0; jj < 4; jj++) + { + accm += *chip->channel[ii].out[jj]; + } + chip->mixbuff[1] += (Bit16s)(accm & chip->channel[ii].chb); + } + + for (ii = 33; ii < 36; ii++) + { + OPL3_SlotCalcFB(&chip->slot[ii]); + OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); + OPL3_SlotGenerate(&chip->slot[ii]); + } + + if ((chip->timer & 0x3f) == 0x3f) + { + chip->tremolopos = (chip->tremolopos + 1) % 210; + } + if (chip->tremolopos < 105) + { + chip->tremolo = chip->tremolopos >> chip->tremoloshift; + } + else + { + chip->tremolo = (210 - chip->tremolopos) >> chip->tremoloshift; + } + + if ((chip->timer & 0x3ff) == 0x3ff) + { + chip->vibpos = (chip->vibpos + 1) & 7; + } + + chip->timer++; + + chip->eg_add = 0; + if (chip->eg_timer) + { + while (shift < 36 && ((chip->eg_timer >> shift) & 1) == 0) + { + shift++; + } + if (shift > 12) + { + chip->eg_add = 0; + } + else + { + chip->eg_add = shift + 1; + } + } + + if (chip->eg_timerrem || chip->eg_state) + { + if (chip->eg_timer == (uint64_t)0xfffffffffU) + { + chip->eg_timer = 0; + chip->eg_timerrem = 1; + } + else + { + chip->eg_timer++; + chip->eg_timerrem = 0; + } + } + + chip->eg_state ^= 1; + + while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt) + { + if (!(chip->writebuf[chip->writebuf_cur].reg & 0x200)) + { + break; + } + chip->writebuf[chip->writebuf_cur].reg &= 0x1ff; + OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_cur].reg, + chip->writebuf[chip->writebuf_cur].data); + chip->writebuf_cur = (chip->writebuf_cur + 1) % OPL_WRITEBUF_SIZE; + } + chip->writebuf_samplecnt++; +} + +void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf) +{ + while (chip->samplecnt >= chip->rateratio) + { + chip->oldsamples[0] = chip->samples[0]; + chip->oldsamples[1] = chip->samples[1]; + OPL3_Generate(chip, chip->samples); + chip->samplecnt -= chip->rateratio; + } + buf[0] = (Bit16s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) + + chip->samples[0] * chip->samplecnt) / chip->rateratio); + buf[1] = (Bit16s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) + + chip->samples[1] * chip->samplecnt) / chip->rateratio); + chip->samplecnt += 1 << RSM_FRAC; +} + +void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) +{ + Bit8u slotnum; + Bit8u channum; + + memset(chip, 0, sizeof(opl3_chip)); + for (slotnum = 0; slotnum < 36; slotnum++) + { + chip->slot[slotnum].chip = chip; + chip->slot[slotnum].mod = &chip->zeromod; + chip->slot[slotnum].eg_rout = 0x1ff; + chip->slot[slotnum].eg_out = 0x1ff; + chip->slot[slotnum].eg_gen = envelope_gen_num_release; + chip->slot[slotnum].trem = (Bit8u*)&chip->zeromod; + chip->slot[slotnum].slot_num = slotnum; + } + for (channum = 0; channum < 18; channum++) + { + chip->channel[channum].slotz[0] = &chip->slot[ch_slot[channum]]; + chip->channel[channum].slotz[1] = &chip->slot[ch_slot[channum] + 3]; + chip->slot[ch_slot[channum]].channel = &chip->channel[channum]; + chip->slot[ch_slot[channum] + 3].channel = &chip->channel[channum]; + if ((channum % 9) < 3) + { + chip->channel[channum].pair = &chip->channel[channum + 3]; + } + else if ((channum % 9) < 6) + { + chip->channel[channum].pair = &chip->channel[channum - 3]; + } + chip->channel[channum].chip = chip; + chip->channel[channum].out[0] = &chip->zeromod; + chip->channel[channum].out[1] = &chip->zeromod; + chip->channel[channum].out[2] = &chip->zeromod; + chip->channel[channum].out[3] = &chip->zeromod; + chip->channel[channum].chtype = ch_2op; + chip->channel[channum].cha = 0xffff; + chip->channel[channum].chb = 0xffff; + chip->channel[channum].ch_num = channum; + OPL3_ChannelSetupAlg(&chip->channel[channum]); + } + chip->noise = 1; + chip->rateratio = (samplerate << RSM_FRAC) / 49716; + chip->tremoloshift = 4; + chip->vibshift = 1; +} + +void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) +{ + Bit8u high = (reg >> 8) & 0x01; + Bit8u regm = reg & 0xff; + switch (regm & 0xf0) + { + case 0x00: + if (high) + { + switch (regm & 0x0f) + { + case 0x04: + OPL3_ChannelSet4Op(chip, v); + break; + case 0x05: + chip->newm = v & 0x01; + break; + } + } + else + { + switch (regm & 0x0f) + { + case 0x08: + chip->nts = (v >> 6) & 0x01; + break; + } + } + break; + case 0x20: + case 0x30: + if (ad_slot[regm & 0x1f] >= 0) + { + OPL3_SlotWrite20(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + } + break; + case 0x40: + case 0x50: + if (ad_slot[regm & 0x1f] >= 0) + { + OPL3_SlotWrite40(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + } + break; + case 0x60: + case 0x70: + if (ad_slot[regm & 0x1f] >= 0) + { + OPL3_SlotWrite60(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + } + break; + case 0x80: + case 0x90: + if (ad_slot[regm & 0x1f] >= 0) + { + OPL3_SlotWrite80(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + } + break; + case 0xe0: + case 0xf0: + if (ad_slot[regm & 0x1f] >= 0) + { + OPL3_SlotWriteE0(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + } + break; + case 0xa0: + if ((regm & 0x0f) < 9) + { + OPL3_ChannelWriteA0(&chip->channel[9 * high + (regm & 0x0f)], v); + } + break; + case 0xb0: + if (regm == 0xbd && !high) + { + chip->tremoloshift = (((v >> 7) ^ 1) << 1) + 2; + chip->vibshift = ((v >> 6) & 0x01) ^ 1; + OPL3_ChannelUpdateRhythm(chip, v); + } + else if ((regm & 0x0f) < 9) + { + OPL3_ChannelWriteB0(&chip->channel[9 * high + (regm & 0x0f)], v); + if (v & 0x20) + { + OPL3_ChannelKeyOn(&chip->channel[9 * high + (regm & 0x0f)]); + } + else + { + OPL3_ChannelKeyOff(&chip->channel[9 * high + (regm & 0x0f)]); + } + } + break; + case 0xc0: + if ((regm & 0x0f) < 9) + { + OPL3_ChannelWriteC0(&chip->channel[9 * high + (regm & 0x0f)], v); + } + break; + } +} + +void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) +{ + Bit64u time1, time2; + + if (chip->writebuf[chip->writebuf_last].reg & 0x200) + { + OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_last].reg & 0x1ff, + chip->writebuf[chip->writebuf_last].data); + + chip->writebuf_cur = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; + chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time; + } + + chip->writebuf[chip->writebuf_last].reg = reg | 0x200; + chip->writebuf[chip->writebuf_last].data = v; + time1 = chip->writebuf_lasttime + OPL_WRITEBUF_DELAY; + time2 = chip->writebuf_samplecnt; + + if (time1 < time2) + { + time1 = time2; + } + + chip->writebuf[chip->writebuf_last].time = time1; + chip->writebuf_lasttime = time1; + chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; +} + +void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) +{ + Bit32u i; + + for(i = 0; i < numsamples; i++) + { + OPL3_GenerateResampled(chip, sndptr); + sndptr += 2; + } +} + +void OPL3_GenerateStreamMix(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) +{ + Bit32u i; + Bit16s sample[2]; + + for(i = 0; i < numsamples; i++) + { + OPL3_GenerateResampled(chip, sample); + sndptr[0] += sample[0]; + sndptr[1] += sample[1]; + sndptr += 2; + } +} diff --git a/src/sound/adlmidi/nukedopl3.h b/src/sound/adlmidi/chips/nuked/nukedopl3.h similarity index 75% rename from src/sound/adlmidi/nukedopl3.h rename to src/sound/adlmidi/chips/nuked/nukedopl3.h index 254f27584..d57cf5fb5 100644 --- a/src/sound/adlmidi/nukedopl3.h +++ b/src/sound/adlmidi/chips/nuked/nukedopl3.h @@ -1,19 +1,16 @@ /* - * Copyright (C) 2013-2016 Alexey Khokholov (Nuke.YKT) + * Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT) * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Nuked OPL3 emulator. * Thanks: @@ -23,21 +20,21 @@ * Tremolo and phase generator calculation information. * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): * OPL2 ROMs. + * siliconpr0n.org(John McMaster, digshadow): + * YMF262 and VRC VII decaps and die shots. * - * version: 1.7.4 + * version: 1.8 */ #ifndef OPL_OPL3_H #define OPL_OPL3_H #include -#include #ifdef __cplusplus extern "C" { #endif - #define OPL_WRITEBUF_SIZE 1024 #define OPL_WRITEBUF_DELAY 2 @@ -82,16 +79,14 @@ struct _opl3_slot { Bit8u reg_rr; Bit8u reg_wf; Bit8u key; + Bit32u pg_reset; Bit32u pg_phase; - Bit32u timer; - - Bit16u maskzero; - Bit8u signpos; - Bit8u phaseshift; + Bit16u pg_phase_out; + Bit8u slot_num; }; struct _opl3_channel { - opl3_slot *slots[2]; + opl3_slot *slotz[2];/*Don't use "slots" keyword to avoid conflict with Qt applications*/ opl3_channel *pair; opl3_chip *chip; Bit16s *out[4]; @@ -103,6 +98,7 @@ struct _opl3_channel { Bit8u alg; Bit8u ksv; Bit16u cha, chb; + Bit8u ch_num; }; typedef struct _opl3_writebuf { @@ -113,8 +109,12 @@ typedef struct _opl3_writebuf { struct _opl3_chip { opl3_channel channel[18]; - opl3_slot chipslot[36]; + opl3_slot slot[36]; Bit16u timer; + Bit64u eg_timer; + Bit8u eg_timerrem; + Bit8u eg_state; + Bit8u eg_add; Bit8u newm; Bit8u nts; Bit8u rhy; @@ -126,6 +126,12 @@ struct _opl3_chip { Bit32u noise; Bit16s zeromod; Bit32s mixbuff[2]; + Bit8u rm_hh_bit2; + Bit8u rm_hh_bit3; + Bit8u rm_hh_bit7; + Bit8u rm_hh_bit8; + Bit8u rm_tc_bit3; + Bit8u rm_tc_bit5; /* OPL3L */ Bit32s rateratio; Bit32s samplecnt; diff --git a/src/sound/adlmidi/nukedopl3.c b/src/sound/adlmidi/chips/nuked/nukedopl3_174.c similarity index 83% rename from src/sound/adlmidi/nukedopl3.c rename to src/sound/adlmidi/chips/nuked/nukedopl3_174.c index 6ae1eb76e..99eab16dc 100644 --- a/src/sound/adlmidi/nukedopl3.c +++ b/src/sound/adlmidi/chips/nuked/nukedopl3_174.c @@ -30,7 +30,7 @@ #include #include #include -#include "nukedopl3.h" +#include "nukedopl3_174.h" #define RSM_FRAC 10 @@ -638,18 +638,18 @@ static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) channel6 = &chip->channel[6]; channel7 = &chip->channel[7]; channel8 = &chip->channel[8]; - channel6->out[0] = &channel6->slots[1]->out; - channel6->out[1] = &channel6->slots[1]->out; + channel6->out[0] = &channel6->slotz[1]->out; + channel6->out[1] = &channel6->slotz[1]->out; channel6->out[2] = &chip->zeromod; channel6->out[3] = &chip->zeromod; - channel7->out[0] = &channel7->slots[0]->out; - channel7->out[1] = &channel7->slots[0]->out; - channel7->out[2] = &channel7->slots[1]->out; - channel7->out[3] = &channel7->slots[1]->out; - channel8->out[0] = &channel8->slots[0]->out; - channel8->out[1] = &channel8->slots[0]->out; - channel8->out[2] = &channel8->slots[1]->out; - channel8->out[3] = &channel8->slots[1]->out; + channel7->out[0] = &channel7->slotz[0]->out; + channel7->out[1] = &channel7->slotz[0]->out; + channel7->out[2] = &channel7->slotz[1]->out; + channel7->out[3] = &channel7->slotz[1]->out; + channel8->out[0] = &channel8->slotz[0]->out; + channel8->out[1] = &channel8->slotz[0]->out; + channel8->out[2] = &channel8->slotz[1]->out; + channel8->out[3] = &channel8->slotz[1]->out; for (chnum = 6; chnum < 9; chnum++) { chip->channel[chnum].chtype = ch_drum; @@ -658,49 +658,49 @@ static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) /*hh*/ if (chip->rhy & 0x01) { - OPL3_EnvelopeKeyOn(channel7->slots[0], egk_drum); + OPL3_EnvelopeKeyOn(channel7->slotz[0], egk_drum); } else { - OPL3_EnvelopeKeyOff(channel7->slots[0], egk_drum); + OPL3_EnvelopeKeyOff(channel7->slotz[0], egk_drum); } /*tc*/ if (chip->rhy & 0x02) { - OPL3_EnvelopeKeyOn(channel8->slots[1], egk_drum); + OPL3_EnvelopeKeyOn(channel8->slotz[1], egk_drum); } else { - OPL3_EnvelopeKeyOff(channel8->slots[1], egk_drum); + OPL3_EnvelopeKeyOff(channel8->slotz[1], egk_drum); } /*tom*/ if (chip->rhy & 0x04) { - OPL3_EnvelopeKeyOn(channel8->slots[0], egk_drum); + OPL3_EnvelopeKeyOn(channel8->slotz[0], egk_drum); } else { - OPL3_EnvelopeKeyOff(channel8->slots[0], egk_drum); + OPL3_EnvelopeKeyOff(channel8->slotz[0], egk_drum); } /*sd*/ if (chip->rhy & 0x08) { - OPL3_EnvelopeKeyOn(channel7->slots[1], egk_drum); + OPL3_EnvelopeKeyOn(channel7->slotz[1], egk_drum); } else { - OPL3_EnvelopeKeyOff(channel7->slots[1], egk_drum); + OPL3_EnvelopeKeyOff(channel7->slotz[1], egk_drum); } /*bd*/ if (chip->rhy & 0x10) { - OPL3_EnvelopeKeyOn(channel6->slots[0], egk_drum); - OPL3_EnvelopeKeyOn(channel6->slots[1], egk_drum); + OPL3_EnvelopeKeyOn(channel6->slotz[0], egk_drum); + OPL3_EnvelopeKeyOn(channel6->slotz[1], egk_drum); } else { - OPL3_EnvelopeKeyOff(channel6->slots[0], egk_drum); - OPL3_EnvelopeKeyOff(channel6->slots[1], egk_drum); + OPL3_EnvelopeKeyOff(channel6->slotz[0], egk_drum); + OPL3_EnvelopeKeyOff(channel6->slotz[1], egk_drum); } } else @@ -709,8 +709,8 @@ static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) { chip->channel[chnum].chtype = ch_2op; OPL3_ChannelSetupAlg(&chip->channel[chnum]); - OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[0], egk_drum); - OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[1], egk_drum); + OPL3_EnvelopeKeyOff(chip->channel[chnum].slotz[0], egk_drum); + OPL3_EnvelopeKeyOff(chip->channel[chnum].slotz[1], egk_drum); } } } @@ -724,18 +724,18 @@ static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data) channel->f_num = (channel->f_num & 0x300) | data; channel->ksv = (channel->block << 1) | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); - OPL3_EnvelopeUpdateKSL(channel->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->slots[1]); - OPL3_EnvelopeUpdateRate(channel->slots[0]); - OPL3_EnvelopeUpdateRate(channel->slots[1]); + OPL3_EnvelopeUpdateKSL(channel->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->slotz[1]); + OPL3_EnvelopeUpdateRate(channel->slotz[0]); + OPL3_EnvelopeUpdateRate(channel->slotz[1]); if (channel->chip->newm && channel->chtype == ch_4op) { channel->pair->f_num = channel->f_num; channel->pair->ksv = channel->ksv; - OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[0]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[1]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[1]); + OPL3_EnvelopeUpdateRate(channel->pair->slotz[0]); + OPL3_EnvelopeUpdateRate(channel->pair->slotz[1]); } } @@ -749,19 +749,19 @@ static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) channel->block = (data >> 2) & 0x07; channel->ksv = (channel->block << 1) | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); - OPL3_EnvelopeUpdateKSL(channel->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->slots[1]); - OPL3_EnvelopeUpdateRate(channel->slots[0]); - OPL3_EnvelopeUpdateRate(channel->slots[1]); + OPL3_EnvelopeUpdateKSL(channel->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->slotz[1]); + OPL3_EnvelopeUpdateRate(channel->slotz[0]); + OPL3_EnvelopeUpdateRate(channel->slotz[1]); if (channel->chip->newm && channel->chtype == ch_4op) { channel->pair->f_num = channel->f_num; channel->pair->block = channel->block; channel->pair->ksv = channel->ksv; - OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[0]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[1]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[1]); + OPL3_EnvelopeUpdateRate(channel->pair->slotz[0]); + OPL3_EnvelopeUpdateRate(channel->pair->slotz[1]); } } @@ -772,12 +772,12 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) switch (channel->alg & 0x01) { case 0x00: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->slots[0]->out; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->slotz[0]->out; break; case 0x01: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->chip->zeromod; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->chip->zeromod; break; } return; @@ -795,43 +795,43 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) switch (channel->alg & 0x03) { case 0x00: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->pair->slots[0]->out; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->slots[1]->out; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->pair->slotz[0]->out; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->slotz[1]->out; channel->out[1] = &channel->chip->zeromod; channel->out[2] = &channel->chip->zeromod; channel->out[3] = &channel->chip->zeromod; break; case 0x01: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->pair->slots[0]->out; - channel->slots[0]->mod = &channel->chip->zeromod; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->pair->slots[1]->out; - channel->out[1] = &channel->slots[1]->out; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->pair->slotz[0]->out; + channel->slotz[0]->mod = &channel->chip->zeromod; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->pair->slotz[1]->out; + channel->out[1] = &channel->slotz[1]->out; channel->out[2] = &channel->chip->zeromod; channel->out[3] = &channel->chip->zeromod; break; case 0x02: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->chip->zeromod; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->pair->slots[0]->out; - channel->out[1] = &channel->slots[1]->out; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->chip->zeromod; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->pair->slotz[0]->out; + channel->out[1] = &channel->slotz[1]->out; channel->out[2] = &channel->chip->zeromod; channel->out[3] = &channel->chip->zeromod; break; case 0x03: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->chip->zeromod; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->chip->zeromod; - channel->out[0] = &channel->pair->slots[0]->out; - channel->out[1] = &channel->slots[0]->out; - channel->out[2] = &channel->slots[1]->out; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->chip->zeromod; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->chip->zeromod; + channel->out[0] = &channel->pair->slotz[0]->out; + channel->out[1] = &channel->slotz[0]->out; + channel->out[2] = &channel->slotz[1]->out; channel->out[3] = &channel->chip->zeromod; break; } @@ -841,18 +841,18 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) switch (channel->alg & 0x01) { case 0x00: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->slots[1]->out; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->slotz[1]->out; channel->out[1] = &channel->chip->zeromod; channel->out[2] = &channel->chip->zeromod; channel->out[3] = &channel->chip->zeromod; break; case 0x01: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->chip->zeromod; - channel->out[0] = &channel->slots[0]->out; - channel->out[1] = &channel->slots[1]->out; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->chip->zeromod; + channel->out[0] = &channel->slotz[0]->out; + channel->out[1] = &channel->slotz[1]->out; channel->out[2] = &channel->chip->zeromod; channel->out[3] = &channel->chip->zeromod; break; @@ -905,21 +905,21 @@ static void OPL3_ChannelKeyOn(opl3_channel *channel) { if (channel->chtype == ch_4op) { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); - OPL3_EnvelopeKeyOn(channel->pair->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->pair->slots[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->pair->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->pair->slotz[1], egk_norm); } else if (channel->chtype == ch_2op || channel->chtype == ch_drum) { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); } } else { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); } } @@ -929,21 +929,21 @@ static void OPL3_ChannelKeyOff(opl3_channel *channel) { if (channel->chtype == ch_4op) { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); - OPL3_EnvelopeKeyOff(channel->pair->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->pair->slots[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->pair->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->pair->slotz[1], egk_norm); } else if (channel->chtype == ch_2op || channel->chtype == ch_drum) { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); } } else { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); } } @@ -997,9 +997,9 @@ static void OPL3_GenerateRhythm1(opl3_chip *chip) channel6 = &chip->channel[6]; channel7 = &chip->channel[7]; channel8 = &chip->channel[8]; - OPL3_SlotGenerate(channel6->slots[0]); - phase14 = (channel7->slots[0]->pg_phase >> 9) & 0x3ff; - phase17 = (channel8->slots[1]->pg_phase >> 9) & 0x3ff; + OPL3_SlotGenerate(channel6->slotz[0]); + phase14 = (channel7->slotz[0]->pg_phase >> 9) & 0x3ff; + phase17 = (channel8->slotz[1]->pg_phase >> 9) & 0x3ff; phase = 0x00; /*hh tc phase bit*/ phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04) @@ -1007,9 +1007,9 @@ static void OPL3_GenerateRhythm1(opl3_chip *chip) /*hh*/ phase = (phasebit << 9) | (0x34 << ((phasebit ^ (chip->noise & 0x01)) << 1)); - OPL3_SlotGeneratePhase(channel7->slots[0], phase); + OPL3_SlotGeneratePhase(channel7->slotz[0], phase); /*tt*/ - OPL3_SlotGenerateZM(channel8->slots[0]); + OPL3_SlotGenerateZM(channel8->slotz[0]); } static void OPL3_GenerateRhythm2(opl3_chip *chip) @@ -1025,22 +1025,22 @@ static void OPL3_GenerateRhythm2(opl3_chip *chip) channel6 = &chip->channel[6]; channel7 = &chip->channel[7]; channel8 = &chip->channel[8]; - OPL3_SlotGenerate(channel6->slots[1]); - phase14 = (channel7->slots[0]->pg_phase >> 9) & 0x3ff; - phase17 = (channel8->slots[1]->pg_phase >> 9) & 0x3ff; + OPL3_SlotGenerate(channel6->slotz[1]); + phase14 = (channel7->slotz[0]->pg_phase >> 9) & 0x3ff; + phase17 = (channel8->slotz[1]->pg_phase >> 9) & 0x3ff; phase = 0x00; /*hh tc phase bit*/ phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04) | (((phase17 >> 2) ^ phase17) & 0x08)) ? 0x01 : 0x00; /*sd*/ phase = (0x100 << ((phase14 >> 8) & 0x01)) ^ ((chip->noise & 0x01) << 8); - OPL3_SlotGeneratePhase(channel7->slots[1], phase); + OPL3_SlotGeneratePhase(channel7->slotz[1], phase); /*tc*/ phase = 0x100 | (phasebit << 9); - OPL3_SlotGeneratePhase(channel8->slots[1], phase); + OPL3_SlotGeneratePhase(channel8->slotz[1], phase); } -void OPL3_Generate(opl3_chip *chip, Bit16s *buf) +void OPL3v17_Generate(opl3_chip *chip, Bit16s *buf) { Bit8u ii; Bit8u jj; @@ -1161,20 +1161,20 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) break; } chip->writebuf[chip->writebuf_cur].reg &= 0x1ff; - OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_cur].reg, + OPL3v17_WriteReg(chip, chip->writebuf[chip->writebuf_cur].reg, chip->writebuf[chip->writebuf_cur].data); chip->writebuf_cur = (chip->writebuf_cur + 1) % OPL_WRITEBUF_SIZE; } chip->writebuf_samplecnt++; } -void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf) +void OPL3v17_GenerateResampled(opl3_chip *chip, Bit16s *buf) { while (chip->samplecnt >= chip->rateratio) { chip->oldsamples[0] = chip->samples[0]; chip->oldsamples[1] = chip->samples[1]; - OPL3_Generate(chip, chip->samples); + OPL3v17_Generate(chip, chip->samples); chip->samplecnt -= chip->rateratio; } buf[0] = (Bit16s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) @@ -1184,7 +1184,7 @@ void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf) chip->samplecnt += 1 << RSM_FRAC; } -void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) +void OPL3v17_Reset(opl3_chip *chip, Bit32u samplerate) { Bit8u slotnum; Bit8u channum; @@ -1202,8 +1202,8 @@ void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) } for (channum = 0; channum < 18; channum++) { - chip->channel[channum].slots[0] = &chip->chipslot[ch_slot[channum]]; - chip->channel[channum].slots[1] = &chip->chipslot[ch_slot[channum] + 3]; + chip->channel[channum].slotz[0] = &chip->chipslot[ch_slot[channum]]; + chip->channel[channum].slotz[1] = &chip->chipslot[ch_slot[channum] + 3]; chip->chipslot[ch_slot[channum]].channel = &chip->channel[channum]; chip->chipslot[ch_slot[channum] + 3].channel = &chip->channel[channum]; if ((channum % 9) < 3) @@ -1230,7 +1230,7 @@ void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) chip->vibshift = 1; } -void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) +void OPL3v17_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) { Bit8u high = (reg >> 8) & 0x01; Bit8u regm = reg & 0xff; @@ -1329,13 +1329,13 @@ void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) } } -void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) +void OPL3v17_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) { Bit64u time1, time2; if (chip->writebuf[chip->writebuf_last].reg & 0x200) { - OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_last].reg & 0x1ff, + OPL3v17_WriteReg(chip, chip->writebuf[chip->writebuf_last].reg & 0x1ff, chip->writebuf[chip->writebuf_last].data); chip->writebuf_cur = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; @@ -1357,13 +1357,13 @@ void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; } -void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) +void OPL3v17_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) { Bit32u i; for(i = 0; i < numsamples; i++) { - OPL3_GenerateResampled(chip, sndptr); + OPL3v17_GenerateResampled(chip, sndptr); sndptr += 2; } } @@ -1372,7 +1372,7 @@ void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) #define OPL3_MAX(A, B) (((A) < (B)) ? (B) : (A)) #define OPL3_CLAMP(V, MIN, MAX) OPL3_MAX(OPL3_MIN(V, MAX), MIN) -void OPL3_GenerateStreamMix(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) +void OPL3v17_GenerateStreamMix(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) { Bit32u i; Bit16s sample[2]; @@ -1380,7 +1380,7 @@ void OPL3_GenerateStreamMix(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) for(i = 0; i < numsamples; i++) { - OPL3_GenerateResampled(chip, sample); + OPL3v17_GenerateResampled(chip, sample); mix[0] = sndptr[0] + sample[0]; mix[1] = sndptr[1] + sample[1]; sndptr[0] = OPL3_CLAMP(mix[0], INT16_MIN, INT16_MAX); diff --git a/src/sound/adlmidi/chips/nuked/nukedopl3_174.h b/src/sound/adlmidi/chips/nuked/nukedopl3_174.h new file mode 100644 index 000000000..240802f4f --- /dev/null +++ b/src/sound/adlmidi/chips/nuked/nukedopl3_174.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2013-2016 Alexey Khokholov (Nuke.YKT) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Nuked OPL3 emulator. + * Thanks: + * MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): + * Feedback and Rhythm part calculation information. + * forums.submarine.org.uk(carbon14, opl3): + * Tremolo and phase generator calculation information. + * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): + * OPL2 ROMs. + * + * version: 1.7.4 + */ + +#ifndef OPL_OPL3_H +#define OPL_OPL3_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define OPL_WRITEBUF_SIZE 1024 +#define OPL_WRITEBUF_DELAY 2 + +typedef uintptr_t Bitu; +typedef intptr_t Bits; +typedef uint64_t Bit64u; +typedef int64_t Bit64s; +typedef uint32_t Bit32u; +typedef int32_t Bit32s; +typedef uint16_t Bit16u; +typedef int16_t Bit16s; +typedef uint8_t Bit8u; +typedef int8_t Bit8s; + +typedef struct _opl3_slot opl3_slot; +typedef struct _opl3_channel opl3_channel; +typedef struct _opl3_chip opl3_chip; + +struct _opl3_slot { + opl3_channel *channel; + opl3_chip *chip; + Bit16s out; + Bit16s fbmod; + Bit16s *mod; + Bit16s prout; + Bit16s eg_rout; + Bit16s eg_out; + Bit8u eg_inc; + Bit8u eg_gen; + Bit8u eg_rate; + Bit8u eg_ksl; + Bit8u *trem; + Bit8u reg_vib; + Bit8u reg_type; + Bit8u reg_ksr; + Bit8u reg_mult; + Bit8u reg_ksl; + Bit8u reg_tl; + Bit8u reg_ar; + Bit8u reg_dr; + Bit8u reg_sl; + Bit8u reg_rr; + Bit8u reg_wf; + Bit8u key; + Bit32u pg_phase; + Bit32u timer; + + Bit16u maskzero; + Bit8u signpos; + Bit8u phaseshift; +}; + +struct _opl3_channel { + opl3_slot *slotz[2];/*Don't use "slots" keyword to avoid conflict with Qt applications*/ + opl3_channel *pair; + opl3_chip *chip; + Bit16s *out[4]; + Bit8u chtype; + Bit16u f_num; + Bit8u block; + Bit8u fb; + Bit8u con; + Bit8u alg; + Bit8u ksv; + Bit16u cha, chb; +}; + +typedef struct _opl3_writebuf { + Bit64u time; + Bit16u reg; + Bit8u data; +} opl3_writebuf; + +struct _opl3_chip { + opl3_channel channel[18]; + opl3_slot chipslot[36]; + Bit16u timer; + Bit8u newm; + Bit8u nts; + Bit8u rhy; + Bit8u vibpos; + Bit8u vibshift; + Bit8u tremolo; + Bit8u tremolopos; + Bit8u tremoloshift; + Bit32u noise; + Bit16s zeromod; + Bit32s mixbuff[2]; + /* OPL3L */ + Bit32s rateratio; + Bit32s samplecnt; + Bit16s oldsamples[2]; + Bit16s samples[2]; + + Bit64u writebuf_samplecnt; + Bit32u writebuf_cur; + Bit32u writebuf_last; + Bit64u writebuf_lasttime; + opl3_writebuf writebuf[OPL_WRITEBUF_SIZE]; +}; + +void OPL3v17_Generate(opl3_chip *chip, Bit16s *buf); +void OPL3v17_GenerateResampled(opl3_chip *chip, Bit16s *buf); +void OPL3v17_Reset(opl3_chip *chip, Bit32u samplerate); +void OPL3v17_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v); +void OPL3v17_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v); +void OPL3v17_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples); +void OPL3v17_GenerateStreamMix(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/sound/adlmidi/chips/nuked_opl3.cpp b/src/sound/adlmidi/chips/nuked_opl3.cpp new file mode 100644 index 000000000..48e5c1736 --- /dev/null +++ b/src/sound/adlmidi/chips/nuked_opl3.cpp @@ -0,0 +1,49 @@ +#include "nuked_opl3.h" +#include "nuked/nukedopl3.h" +#include + +NukedOPL3::NukedOPL3() : + OPLChipBaseT() +{ + m_chip = new opl3_chip; + setRate(m_rate); +} + +NukedOPL3::~NukedOPL3() +{ + opl3_chip *chip_r = reinterpret_cast(m_chip); + delete chip_r; +} + +void NukedOPL3::setRate(uint32_t rate) +{ + OPLChipBaseT::setRate(rate); + opl3_chip *chip_r = reinterpret_cast(m_chip); + std::memset(chip_r, 0, sizeof(opl3_chip)); + OPL3_Reset(chip_r, rate); +} + +void NukedOPL3::reset() +{ + OPLChipBaseT::reset(); + opl3_chip *chip_r = reinterpret_cast(m_chip); + std::memset(chip_r, 0, sizeof(opl3_chip)); + OPL3_Reset(chip_r, m_rate); +} + +void NukedOPL3::writeReg(uint16_t addr, uint8_t data) +{ + opl3_chip *chip_r = reinterpret_cast(m_chip); + OPL3_WriteRegBuffered(chip_r, addr, data); +} + +void NukedOPL3::nativeGenerate(int16_t *frame) +{ + opl3_chip *chip_r = reinterpret_cast(m_chip); + OPL3_Generate(chip_r, frame); +} + +const char *NukedOPL3::emulatorName() +{ + return "Nuked OPL3 (v 1.8)"; +} diff --git a/src/sound/adlmidi/chips/nuked_opl3.h b/src/sound/adlmidi/chips/nuked_opl3.h new file mode 100644 index 000000000..1b34e9ab5 --- /dev/null +++ b/src/sound/adlmidi/chips/nuked_opl3.h @@ -0,0 +1,23 @@ +#ifndef NUKED_OPL3_H +#define NUKED_OPL3_H + +#include "opl_chip_base.h" + +class NukedOPL3 final : public OPLChipBaseT +{ + void *m_chip; +public: + NukedOPL3(); + ~NukedOPL3() override; + + bool canRunAtPcmRate() const override { return false; } + void setRate(uint32_t rate) override; + void reset() override; + void writeReg(uint16_t addr, uint8_t data) override; + void nativePreGenerate() override {} + void nativePostGenerate() override {} + void nativeGenerate(int16_t *frame) override; + const char *emulatorName() override; +}; + +#endif // NUKED_OPL3_H diff --git a/src/sound/adlmidi/chips/nuked_opl3_v174.cpp b/src/sound/adlmidi/chips/nuked_opl3_v174.cpp new file mode 100644 index 000000000..e24b2e706 --- /dev/null +++ b/src/sound/adlmidi/chips/nuked_opl3_v174.cpp @@ -0,0 +1,49 @@ +#include "nuked_opl3_v174.h" +#include "nuked/nukedopl3_174.h" +#include + +NukedOPL3v174::NukedOPL3v174() : + OPLChipBaseT() +{ + m_chip = new opl3_chip; + setRate(m_rate); +} + +NukedOPL3v174::~NukedOPL3v174() +{ + opl3_chip *chip_r = reinterpret_cast(m_chip); + delete chip_r; +} + +void NukedOPL3v174::setRate(uint32_t rate) +{ + OPLChipBaseT::setRate(rate); + opl3_chip *chip_r = reinterpret_cast(m_chip); + std::memset(chip_r, 0, sizeof(opl3_chip)); + OPL3v17_Reset(chip_r, rate); +} + +void NukedOPL3v174::reset() +{ + OPLChipBaseT::reset(); + opl3_chip *chip_r = reinterpret_cast(m_chip); + std::memset(chip_r, 0, sizeof(opl3_chip)); + OPL3v17_Reset(chip_r, m_rate); +} + +void NukedOPL3v174::writeReg(uint16_t addr, uint8_t data) +{ + opl3_chip *chip_r = reinterpret_cast(m_chip); + OPL3v17_WriteReg(chip_r, addr, data); +} + +void NukedOPL3v174::nativeGenerate(int16_t *frame) +{ + opl3_chip *chip_r = reinterpret_cast(m_chip); + OPL3v17_Generate(chip_r, frame); +} + +const char *NukedOPL3v174::emulatorName() +{ + return "Nuked OPL3 (v 1.7.4)"; +} diff --git a/src/sound/adlmidi/chips/nuked_opl3_v174.h b/src/sound/adlmidi/chips/nuked_opl3_v174.h new file mode 100644 index 000000000..f14221fe0 --- /dev/null +++ b/src/sound/adlmidi/chips/nuked_opl3_v174.h @@ -0,0 +1,23 @@ +#ifndef NUKED_OPL3174_H +#define NUKED_OPL3174_H + +#include "opl_chip_base.h" + +class NukedOPL3v174 final : public OPLChipBaseT +{ + void *m_chip; +public: + NukedOPL3v174(); + ~NukedOPL3v174() override; + + bool canRunAtPcmRate() const override { return false; } + void setRate(uint32_t rate) override; + void reset() override; + void writeReg(uint16_t addr, uint8_t data) override; + void nativePreGenerate() override {} + void nativePostGenerate() override {} + void nativeGenerate(int16_t *frame) override; + const char *emulatorName() override; +}; + +#endif // NUKED_OPL3174_H diff --git a/src/sound/adlmidi/chips/opl_chip_base.h b/src/sound/adlmidi/chips/opl_chip_base.h new file mode 100644 index 000000000..879d6dad8 --- /dev/null +++ b/src/sound/adlmidi/chips/opl_chip_base.h @@ -0,0 +1,129 @@ +#ifndef ONP_CHIP_BASE_H +#define ONP_CHIP_BASE_H + +#include +#include + +#if !defined(_MSC_VER) && (__cplusplus <= 199711L) +#define final +#define override +#endif + +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) +class VResampler; +#endif + +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) +extern void adl_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate); +#endif + +class OPLChipBase +{ +public: + enum { nativeRate = 49716 }; +protected: + uint32_t m_id; + uint32_t m_rate; +public: + OPLChipBase(); + virtual ~OPLChipBase(); + + uint32_t chipId() const { return m_id; } + void setChipId(uint32_t id) { m_id = id; } + + virtual bool canRunAtPcmRate() const = 0; + virtual bool isRunningAtPcmRate() const = 0; + virtual bool setRunningAtPcmRate(bool r) = 0; +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + virtual void setAudioTickHandlerInstance(void *instance) = 0; +#endif + + virtual void setRate(uint32_t rate) = 0; + virtual uint32_t effectiveRate() const = 0; + virtual void reset() = 0; + virtual void writeReg(uint16_t addr, uint8_t data) = 0; + + virtual void nativePreGenerate() = 0; + virtual void nativePostGenerate() = 0; + virtual void nativeGenerate(int16_t *frame) = 0; + + virtual void generate(int16_t *output, size_t frames) = 0; + virtual void generateAndMix(int16_t *output, size_t frames) = 0; + virtual void generate32(int32_t *output, size_t frames) = 0; + virtual void generateAndMix32(int32_t *output, size_t frames) = 0; + + virtual const char* emulatorName() = 0; +private: + OPLChipBase(const OPLChipBase &c); + OPLChipBase &operator=(const OPLChipBase &c); +}; + +// A base class providing F-bounded generic and efficient implementations, +// supporting resampling of chip outputs +template +class OPLChipBaseT : public OPLChipBase +{ +public: + OPLChipBaseT(); + virtual ~OPLChipBaseT(); + + bool isRunningAtPcmRate() const override; + bool setRunningAtPcmRate(bool r) override; +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + void setAudioTickHandlerInstance(void *instance); +#endif + + virtual void setRate(uint32_t rate) override; + uint32_t effectiveRate() const override; + virtual void reset() override; + void generate(int16_t *output, size_t frames) override; + void generateAndMix(int16_t *output, size_t frames) override; + void generate32(int32_t *output, size_t frames) override; + void generateAndMix32(int32_t *output, size_t frames) override; +private: + bool m_runningAtPcmRate; +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + void *m_audioTickHandlerInstance; +#endif + void nativeTick(int16_t *frame); + void setupResampler(uint32_t rate); + void resetResampler(); + void resampledGenerate(int32_t *output); +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + VResampler *m_resampler; +#else + int32_t m_oldsamples[2]; + int32_t m_samples[2]; + int32_t m_samplecnt; + int32_t m_rateratio; + enum { rsm_frac = 10 }; +#endif + // amplitude scale factors in and out of resampler, varying for chips; + // values are OK to "redefine", the static polymorphism will accept it. + enum { resamplerPreAmplify = 1, resamplerPostAttenuate = 1 }; +}; + +// A base class which provides frame-by-frame interfaces on emulations which +// don't have a routine for it. It produces outputs in fixed size buffers. +// Fast register updates will suffer some latency because of buffering. +template +class OPLChipBaseBufferedT : public OPLChipBaseT +{ +public: + OPLChipBaseBufferedT() + : OPLChipBaseT(), m_bufferIndex(0) {} + virtual ~OPLChipBaseBufferedT() + {} +public: + void reset() override; + void nativeGenerate(int16_t *frame) override; +protected: + virtual void nativeGenerateN(int16_t *output, size_t frames) = 0; +private: + unsigned m_bufferIndex; + int16_t m_buffer[2 * Buffer]; +}; + +#include "opl_chip_base.tcc" + +#endif // ONP_CHIP_BASE_H diff --git a/src/sound/adlmidi/chips/opl_chip_base.tcc b/src/sound/adlmidi/chips/opl_chip_base.tcc new file mode 100644 index 000000000..48ad103fa --- /dev/null +++ b/src/sound/adlmidi/chips/opl_chip_base.tcc @@ -0,0 +1,294 @@ +#include "opl_chip_base.h" +#include + +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) +#include +#endif + +#if !defined(LIKELY) && defined(__GNUC__) +#define LIKELY(x) __builtin_expect((x), 1) +#elif !defined(LIKELY) +#define LIKELY(x) (x) +#endif + +#if !defined(UNLIKELY) && defined(__GNUC__) +#define UNLIKELY(x) __builtin_expect((x), 0) +#elif !defined(UNLIKELY) +#define UNLIKELY(x) (x) +#endif + +/* OPLChipBase */ + +inline OPLChipBase::OPLChipBase() : + m_id(0), + m_rate(44100) +{ +} + +inline OPLChipBase::~OPLChipBase() +{ +} + +/* OPLChipBaseT */ + +template +OPLChipBaseT::OPLChipBaseT() + : OPLChipBase(), + m_runningAtPcmRate(false) +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + , + m_audioTickHandlerInstance(NULL) +#endif +{ +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + m_resampler = new VResampler; +#endif + setupResampler(m_rate); +} + +template +OPLChipBaseT::~OPLChipBaseT() +{ +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + delete m_resampler; +#endif +} + +template +bool OPLChipBaseT::isRunningAtPcmRate() const +{ + return m_runningAtPcmRate; +} + +template +bool OPLChipBaseT::setRunningAtPcmRate(bool r) +{ + if(r != m_runningAtPcmRate) + { + if(r && !static_cast(this)->canRunAtPcmRate()) + return false; + m_runningAtPcmRate = r; + static_cast(this)->setRate(m_rate); + } + return true; +} + +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) +template +void OPLChipBaseT::setAudioTickHandlerInstance(void *instance) +{ + m_audioTickHandlerInstance = instance; +} +#endif + +template +void OPLChipBaseT::setRate(uint32_t rate) +{ + uint32_t oldRate = m_rate; + m_rate = rate; + if(rate != oldRate) + setupResampler(rate); + else + resetResampler(); +} + +template +uint32_t OPLChipBaseT::effectiveRate() const +{ + return m_runningAtPcmRate ? m_rate : (uint32_t)nativeRate; +} + +template +void OPLChipBaseT::reset() +{ + resetResampler(); +} + +template +void OPLChipBaseT::generate(int16_t *output, size_t frames) +{ + static_cast(this)->nativePreGenerate(); + for(size_t i = 0; i < frames; ++i) + { + int32_t frame[2]; + static_cast(this)->resampledGenerate(frame); + for (unsigned c = 0; c < 2; ++c) { + int32_t temp = frame[c]; + temp = (temp > -32768) ? temp : -32768; + temp = (temp < 32767) ? temp : 32767; + output[c] = (int16_t)temp; + } + output += 2; + } + static_cast(this)->nativePostGenerate(); +} + +template +void OPLChipBaseT::generateAndMix(int16_t *output, size_t frames) +{ + static_cast(this)->nativePreGenerate(); + for(size_t i = 0; i < frames; ++i) + { + int32_t frame[2]; + static_cast(this)->resampledGenerate(frame); + for (unsigned c = 0; c < 2; ++c) { + int32_t temp = (int32_t)output[c] + frame[c]; + temp = (temp > -32768) ? temp : -32768; + temp = (temp < 32767) ? temp : 32767; + output[c] = (int16_t)temp; + } + output += 2; + } + static_cast(this)->nativePostGenerate(); +} + +template +void OPLChipBaseT::generate32(int32_t *output, size_t frames) +{ + static_cast(this)->nativePreGenerate(); + for(size_t i = 0; i < frames; ++i) + { + static_cast(this)->resampledGenerate(output); + output += 2; + } + static_cast(this)->nativePostGenerate(); +} + +template +void OPLChipBaseT::generateAndMix32(int32_t *output, size_t frames) +{ + static_cast(this)->nativePreGenerate(); + for(size_t i = 0; i < frames; ++i) + { + int32_t frame[2]; + static_cast(this)->resampledGenerate(frame); + output[0] += frame[0]; + output[1] += frame[1]; + output += 2; + } + static_cast(this)->nativePostGenerate(); +} + +template +void OPLChipBaseT::nativeTick(int16_t *frame) +{ +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + adl_audioTickHandler(m_audioTickHandlerInstance, m_id, effectiveRate()); +#endif + static_cast(this)->nativeGenerate(frame); +} + +template +void OPLChipBaseT::setupResampler(uint32_t rate) +{ +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + m_resampler->setup(rate * (1.0 / 49716), 2, 48); +#else + m_oldsamples[0] = m_oldsamples[1] = 0; + m_samples[0] = m_samples[1] = 0; + m_samplecnt = 0; + m_rateratio = (int32_t)((rate << rsm_frac) / 49716); +#endif +} + +template +void OPLChipBaseT::resetResampler() +{ +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + m_resampler->reset(); +#else + m_oldsamples[0] = m_oldsamples[1] = 0; + m_samples[0] = m_samples[1] = 0; + m_samplecnt = 0; +#endif +} + +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) +template +void OPLChipBaseT::resampledGenerate(int32_t *output) +{ + if(UNLIKELY(m_runningAtPcmRate)) + { + int16_t in[2]; + static_cast(this)->nativeTick(in); + output[0] = (int32_t)in[0] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + output[1] = (int32_t)in[1] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + return; + } + + VResampler *rsm = m_resampler; + float scale = (float)T::resamplerPreAmplify / + (float)T::resamplerPostAttenuate; + float f_in[2]; + float f_out[2]; + rsm->inp_count = 0; + rsm->inp_data = f_in; + rsm->out_count = 1; + rsm->out_data = f_out; + while(rsm->process(), rsm->out_count != 0) + { + int16_t in[2]; + static_cast(this)->nativeTick(in); + f_in[0] = scale * (float)in[0]; + f_in[1] = scale * (float)in[1]; + rsm->inp_count = 1; + rsm->inp_data = f_in; + rsm->out_count = 1; + rsm->out_data = f_out; + } + output[0] = std::lround(f_out[0]); + output[1] = std::lround(f_out[1]); +} +#else +template +void OPLChipBaseT::resampledGenerate(int32_t *output) +{ + if(UNLIKELY(m_runningAtPcmRate)) + { + int16_t in[2]; + static_cast(this)->nativeTick(in); + output[0] = (int32_t)in[0] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + output[1] = (int32_t)in[1] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + return; + } + + int32_t samplecnt = m_samplecnt; + const int32_t rateratio = m_rateratio; + while(samplecnt >= rateratio) + { + m_oldsamples[0] = m_samples[0]; + m_oldsamples[1] = m_samples[1]; + int16_t buffer[2]; + static_cast(this)->nativeTick(buffer); + m_samples[0] = buffer[0] * T::resamplerPreAmplify; + m_samples[1] = buffer[1] * T::resamplerPreAmplify; + samplecnt -= rateratio; + } + output[0] = (int32_t)(((m_oldsamples[0] * (rateratio - samplecnt) + + m_samples[0] * samplecnt) / rateratio)/T::resamplerPostAttenuate); + output[1] = (int32_t)(((m_oldsamples[1] * (rateratio - samplecnt) + + m_samples[1] * samplecnt) / rateratio)/T::resamplerPostAttenuate); + m_samplecnt = samplecnt + (1 << rsm_frac); +} +#endif + +/* OPLChipBaseBufferedT */ + +template +void OPLChipBaseBufferedT::reset() +{ + OPLChipBaseT::reset(); + m_bufferIndex = 0; +} + +template +void OPLChipBaseBufferedT::nativeGenerate(int16_t *frame) +{ + unsigned bufferIndex = m_bufferIndex; + if(bufferIndex == 0) + static_cast(this)->nativeGenerateN(m_buffer, Buffer); + frame[0] = m_buffer[2 * bufferIndex]; + frame[1] = m_buffer[2 * bufferIndex + 1]; + bufferIndex = (bufferIndex + 1 < Buffer) ? (bufferIndex + 1) : 0; + m_bufferIndex = bufferIndex; +} diff --git a/src/sound/adlmidi/dbopl.cpp b/src/sound/adlmidi/dbopl.cpp deleted file mode 100644 index fb28e207d..000000000 --- a/src/sound/adlmidi/dbopl.cpp +++ /dev/null @@ -1,2045 +0,0 @@ -#ifdef ADLMIDI_USE_DOSBOX_OPL - -#ifdef __MINGW32__ -typedef struct vswprintf {} swprintf; -#endif -/* - * Copyright (C) 2002-2010 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - DOSBox implementation of a combined Yamaha YMF262 and Yamaha YM3812 emulator. - Enabling the opl3 bit will switch the emulator to stereo opl3 output instead of regular mono opl2 - Except for the table generation it's all integer math - Can choose different types of generators, using muls and bigger tables, try different ones for slower platforms - The generation was based on the MAME implementation but tried to have it use less memory and be faster in general - MAME uses much bigger envelope tables and this will be the biggest cause of it sounding different at times - - //TODO Don't delay first operator 1 sample in opl3 mode - //TODO Maybe not use class method pointers but a regular function pointers with operator as first parameter - //TODO Fix panning for the Percussion channels, would any opl3 player use it and actually really change it though? - //TODO Check if having the same accuracy in all frequency multipliers sounds better or not - - //DUNNO Keyon in 4op, switch to 2op without keyoff. -*/ - -/* $Id: dbopl.cpp,v 1.10 2009-06-10 19:54:51 harekiet Exp $ */ - - -#include -#include -#include -#include "dbopl.h" - -#define DB_MAX(x, y) ((x) > (y) ? (x) : (y)) -#define DB_MIN(x, y) ((x) < (y) ? (x) : (y)) - -#define DBOPL_CLAMP(V, MIN, MAX) DB_MAX(DB_MIN(V, (MAX)), (MIN)) - -#ifndef PI -#define PI 3.14159265358979323846 -#endif - -namespace DBOPL -{ - -#define OPLRATE ((double)(14318180.0 / 288.0)) -#define TREMOLO_TABLE 52 - - //Try to use most precision for frequencies - //Else try to keep different waves in synch - //#define WAVE_PRECISION 1 - #ifndef WAVE_PRECISION - //Wave bits available in the top of the 32bit range - //Original adlib uses 10.10, we use 10.22 -#define WAVE_BITS 10 - #else - //Need some extra bits at the top to have room for octaves and frequency multiplier - //We support to 8 times lower rate - //128 * 15 * 8 = 15350, 2^13.9, so need 14 bits -#define WAVE_BITS 14 - #endif -#define WAVE_SH ( 32 - WAVE_BITS ) -#define WAVE_MASK ( ( 1 << WAVE_SH ) - 1 ) - - //Use the same accuracy as the waves -#define LFO_SH ( WAVE_SH - 10 ) - //LFO is controlled by our tremolo 256 sample limit -#define LFO_MAX ( 256 << ( LFO_SH ) ) - - - //Maximum amount of attenuation bits - //Envelope goes to 511, 9 bits - #if (DBOPL_WAVE == WAVE_TABLEMUL ) - //Uses the value directly -#define ENV_BITS ( 9 ) - #else - //Add 3 bits here for more accuracy and would have to be shifted up either way -#define ENV_BITS ( 9 ) - #endif - //Limits of the envelope with those bits and when the envelope goes silent -#define ENV_MIN 0 -#define ENV_EXTRA ( ENV_BITS - 9 ) -#define ENV_MAX ( 511 << ENV_EXTRA ) -#define ENV_LIMIT ( ( 12 * 256) >> ( 3 - ENV_EXTRA ) ) -#define ENV_SILENT( _X_ ) ( (_X_) >= ENV_LIMIT ) - - //Attack/decay/release rate counter shift -#define RATE_SH 24 -#define RATE_MASK ( ( 1 << RATE_SH ) - 1 ) - //Has to fit within 16bit lookuptable -#define MUL_SH 16 - - //Check some ranges - #if ENV_EXTRA > 3 -#error Too many envelope bits - #endif - - - //How much to substract from the base value for the final attenuation - static const Bit8u KslCreateTable[16] = - { - //0 will always be be lower than 7 * 8 - 64, 32, 24, 19, - 16, 12, 11, 10, - 8, 6, 5, 4, - 3, 2, 1, 0, - }; - -#define M(_X_) ((Bit8u)( (_X_) * 2)) - static const Bit8u FreqCreateTable[16] = - { - M(0.5), M(1), M(2), M(3), M(4), M(5), M(6), M(7), - M(8), M(9), M(10), M(10), M(12), M(12), M(15), M(15) - }; -#undef M - - //We're not including the highest attack rate, that gets a special value - static const Bit8u AttackSamplesTable[13] = - { - 69, 55, 46, 40, - 35, 29, 23, 20, - 19, 15, 11, 10, - 9 - }; - //On a real opl these values take 8 samples to reach and are based upon larger tables - static const Bit8u EnvelopeIncreaseTable[13] = - { - 4, 5, 6, 7, - 8, 10, 12, 14, - 16, 20, 24, 28, - 32, - }; - - #if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG ) - static Bit16u ExpTable[ 256 ]; - #endif - - #if ( DBOPL_WAVE == WAVE_HANDLER ) - //PI table used by WAVEHANDLER - static Bit16u SinTable[ 512 ]; - #endif - - #if ( DBOPL_WAVE > WAVE_HANDLER ) - //Layout of the waveform table in 512 entry intervals - //With overlapping waves we reduce the table to half it's size - - // | |//\\|____|WAV7|//__|/\ |____|/\/\| - // |\\//| | |WAV7| | \/| | | - // |06 |0126|17 |7 |3 |4 |4 5 |5 | - - //6 is just 0 shifted and masked - - static Bit16s WaveTable[ 8 * 512 ]; - //Distance into WaveTable the wave starts - static const Bit16u WaveBaseTable[8] = - { - 0x000, 0x200, 0x200, 0x800, - 0xa00, 0xc00, 0x100, 0x400, - - }; - //Mask the counter with this - static const Bit16u WaveMaskTable[8] = - { - 1023, 1023, 511, 511, - 1023, 1023, 512, 1023, - }; - - //Where to start the counter on at keyon - static const Bit16u WaveStartTable[8] = - { - 512, 0, 0, 0, - 0, 512, 512, 256, - }; - #endif - - #if ( DBOPL_WAVE == WAVE_TABLEMUL ) - static Bit16u MulTable[ 384 ]; - #endif - - static Bit8u KslTable[ 8 * 16 ]; - static Bit8u TremoloTable[ TREMOLO_TABLE ]; - //Start of a channel behind the chip struct start - static Bit16u ChanOffsetTable[32]; - //Start of an operator behind the chip struct start - static Bit16u OpOffsetTable[64]; - - //The lower bits are the shift of the operator vibrato value - //The highest bit is right shifted to generate -1 or 0 for negation - //So taking the highest input value of 7 this gives 3, 7, 3, 0, -3, -7, -3, 0 - static const Bit8s VibratoTable[ 8 ] = - { - 1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00, - 1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80 - }; - - //Shift strength for the ksl value determined by ksl strength - static const Bit8u KslShiftTable[4] = - { - 31, 1, 2, 0 - }; - - //Generate a table index and table shift value using input value from a selected rate - static void EnvelopeSelect(Bit8u val, Bit8u &index, Bit8u &shift) - { - if(val < 13 * 4) //Rate 0 - 12 - { - shift = 12 - (val >> 2); - index = val & 3; - } - else if(val < 15 * 4) //rate 13 - 14 - { - shift = 0; - index = val - 12 * 4; - } - else //rate 15 and up - { - shift = 0; - index = 12; - } - } - - #if ( DBOPL_WAVE == WAVE_HANDLER ) - /* - Generate the different waveforms out of the sine/exponetial table using handlers - */ - static inline Bits MakeVolume(Bitu wave, Bitu volume) - { - Bitu total = wave + volume; - Bitu index = total & 0xff; - Bitu sig = ExpTable[ index ]; - Bitu exp = total >> 8; - #if 0 - - //Check if we overflow the 31 shift limit - if(exp >= 32) - LOG_MSG("WTF %d %d", total, exp); - - #endif - return (sig >> exp); - }; - - static Bits DB_FASTCALL WaveForm0(Bitu i, Bitu volume) - { - Bits neg = 0 - ((i >> 9) & 1); //Create ~0 or 0 - Bitu wave = SinTable[i & 511]; - return (MakeVolume(wave, volume) ^ neg) - neg; - } - static Bits DB_FASTCALL WaveForm1(Bitu i, Bitu volume) - { - Bit32u wave = SinTable[i & 511]; - wave |= (((i ^ 512) & 512) - 1) >> (32 - 12); - return MakeVolume(wave, volume); - } - static Bits DB_FASTCALL WaveForm2(Bitu i, Bitu volume) - { - Bitu wave = SinTable[i & 511]; - return MakeVolume(wave, volume); - } - static Bits DB_FASTCALL WaveForm3(Bitu i, Bitu volume) - { - Bitu wave = SinTable[i & 255]; - wave |= (((i ^ 256) & 256) - 1) >> (32 - 12); - return MakeVolume(wave, volume); - } - static Bits DB_FASTCALL WaveForm4(Bitu i, Bitu volume) - { - //Twice as fast - i <<= 1; - Bits neg = 0 - ((i >> 9) & 1); //Create ~0 or 0 - Bitu wave = SinTable[i & 511]; - wave |= (((i ^ 512) & 512) - 1) >> (32 - 12); - return (MakeVolume(wave, volume) ^ neg) - neg; - } - static Bits DB_FASTCALL WaveForm5(Bitu i, Bitu volume) - { - //Twice as fast - i <<= 1; - Bitu wave = SinTable[i & 511]; - wave |= (((i ^ 512) & 512) - 1) >> (32 - 12); - return MakeVolume(wave, volume); - } - static Bits DB_FASTCALL WaveForm6(Bitu i, Bitu volume) - { - Bits neg = 0 - ((i >> 9) & 1); //Create ~0 or 0 - return (MakeVolume(0, volume) ^ neg) - neg; - } - static Bits DB_FASTCALL WaveForm7(Bitu i, Bitu volume) - { - //Negative is reversed here - Bits neg = ((i >> 9) & 1) - 1; - Bitu wave = (i << 3); - //When negative the volume also runs backwards - wave = ((wave ^ neg) - neg) & 4095; - return (MakeVolume(wave, volume) ^ neg) - neg; - } - - static const WaveHandler WaveHandlerTable[8] = - { - WaveForm0, WaveForm1, WaveForm2, WaveForm3, - WaveForm4, WaveForm5, WaveForm6, WaveForm7 - }; - - #endif - - /* - Operator - */ - - //We zero out when rate == 0 - inline void Operator::UpdateAttack(const Chip *chip) - { - Bit8u rate = reg60 >> 4; - - if(rate) - { - Bit8u val = (rate << 2) + ksr; - attackAdd = chip->attackRates[ val ]; - rateZero &= ~(1 << ATTACK); - } - else - { - attackAdd = 0; - rateZero |= (1 << ATTACK); - } - } - inline void Operator::UpdateDecay(const Chip *chip) - { - Bit8u rate = reg60 & 0xf; - - if(rate) - { - Bit8u val = (rate << 2) + ksr; - decayAdd = chip->linearRates[ val ]; - rateZero &= ~(1 << DECAY); - } - else - { - decayAdd = 0; - rateZero |= (1 << DECAY); - } - } - inline void Operator::UpdateRelease(const Chip *chip) - { - Bit8u rate = reg80 & 0xf; - - if(rate) - { - Bit8u val = (rate << 2) + ksr; - releaseAdd = chip->linearRates[ val ]; - rateZero &= ~(1 << RELEASE); - - if(!(reg20 & MASK_SUSTAIN)) - rateZero &= ~(1 << SUSTAIN); - } - else - { - rateZero |= (1 << RELEASE); - releaseAdd = 0; - - if(!(reg20 & MASK_SUSTAIN)) - rateZero |= (1 << SUSTAIN); - } - } - - inline void Operator::UpdateAttenuation() - { - Bit8u kslBase = (Bit8u)((chanData >> SHIFT_KSLBASE) & 0xff); - Bit32u tl = reg40 & 0x3f; - Bit8u kslShift = KslShiftTable[ reg40 >> 6 ]; - //Make sure the attenuation goes to the right bits - totalLevel = tl << (ENV_BITS - 7); //Total level goes 2 bits below max - totalLevel += (kslBase << ENV_EXTRA) >> kslShift; - } - - void Operator::UpdateFrequency() - { - Bit32u freq = chanData & ((1 << 10) - 1); - Bit32u block = (chanData >> 10) & 0xff; - #ifdef WAVE_PRECISION - block = 7 - block; - waveAdd = (freq * freqMul) >> block; - #else - waveAdd = (freq << block) * freqMul; - #endif - - if(reg20 & MASK_VIBRATO) - { - vibStrength = (Bit8u)(freq >> 7); - #ifdef WAVE_PRECISION - vibrato = (vibStrength * freqMul) >> block; - #else - vibrato = (vibStrength << block) * freqMul; - #endif - } - else - { - vibStrength = 0; - vibrato = 0; - } - } - - void Operator::UpdateRates(const Chip *chip) - { - //Mame seems to reverse this where enabling ksr actually lowers - //the rate, but pdf manuals says otherwise? - Bit8u newKsr = (Bit8u)((chanData >> SHIFT_KEYCODE) & 0xff); - - if(!(reg20 & MASK_KSR)) - newKsr >>= 2; - - if(ksr == newKsr) - return; - - ksr = newKsr; - UpdateAttack(chip); - UpdateDecay(chip); - UpdateRelease(chip); - } - - INLINE Bit32s Operator::RateForward(Bit32u add) - { - rateIndex += add; - Bit32s ret = rateIndex >> RATE_SH; - rateIndex = rateIndex & RATE_MASK; - return ret; - } - - template< Operator::State yes> - Bits Operator::TemplateVolume() - { - Bit32s vol = volume; - Bit32s change; - - switch(yes) - { - case OFF: - return ENV_MAX; - - case ATTACK: - change = RateForward(attackAdd); - - if(!change) - return vol; - - vol += ((~vol) * change) >> 3; - - if(vol < ENV_MIN) - { - volume = ENV_MIN; - rateIndex = 0; - SetState(DECAY); - return ENV_MIN; - } - - break; - - case DECAY: - vol += RateForward(decayAdd); - - if(GCC_UNLIKELY(vol >= sustainLevel)) - { - //Check if we didn't overshoot max attenuation, then just go off - if(GCC_UNLIKELY(vol >= ENV_MAX)) - { - volume = ENV_MAX; - SetState(OFF); - return ENV_MAX; - } - - //Continue as sustain - rateIndex = 0; - SetState(SUSTAIN); - } - - break; - - case SUSTAIN: - if(reg20 & MASK_SUSTAIN) - return vol; - - //In sustain phase, but not sustaining, do regular release - case RELEASE: - vol += RateForward(releaseAdd);; - - if(GCC_UNLIKELY(vol >= ENV_MAX)) - { - volume = ENV_MAX; - SetState(OFF); - return ENV_MAX; - } - - break; - } - - volume = vol; - return vol; - } - - static const VolumeHandler VolumeHandlerTable[5] = - { - &Operator::TemplateVolume< Operator::OFF >, - &Operator::TemplateVolume< Operator::RELEASE >, - &Operator::TemplateVolume< Operator::SUSTAIN >, - &Operator::TemplateVolume< Operator::DECAY >, - &Operator::TemplateVolume< Operator::ATTACK > - }; - - INLINE Bitu Operator::ForwardVolume() - { - return currentLevel + (this->*volHandler)(); - } - - - INLINE Bitu Operator::ForwardWave() - { - waveIndex += waveCurrent; - return waveIndex >> WAVE_SH; - } - - void Operator::Write20(const Chip *chip, Bit8u val) - { - Bit8u change = (reg20 ^ val); - - if(!change) - return; - - reg20 = val; - //Shift the tremolo bit over the entire register, saved a branch, YES! - tremoloMask = (Bit8s)(val) >> 7; - tremoloMask &= ~((1 << ENV_EXTRA) - 1); - - //Update specific features based on changes - if(change & MASK_KSR) - UpdateRates(chip); - - //With sustain enable the volume doesn't change - if(reg20 & MASK_SUSTAIN || (!releaseAdd)) - rateZero |= (1 << SUSTAIN); - else - rateZero &= ~(1 << SUSTAIN); - - //Frequency multiplier or vibrato changed - if(change & (0xf | MASK_VIBRATO)) - { - freqMul = chip->freqMul[ val & 0xf ]; - UpdateFrequency(); - } - } - - void Operator::Write40(const Chip * /*chip*/, Bit8u val) - { - if(!(reg40 ^ val)) - return; - - reg40 = val; - UpdateAttenuation(); - } - - void Operator::Write60(const Chip *chip, Bit8u val) - { - Bit8u change = reg60 ^ val; - reg60 = val; - - if(change & 0x0f) - UpdateDecay(chip); - - if(change & 0xf0) - UpdateAttack(chip); - } - - void Operator::Write80(const Chip *chip, Bit8u val) - { - Bit8u change = (reg80 ^ val); - - if(!change) - return; - - reg80 = val; - Bit8u sustain = val >> 4; - //Turn 0xf into 0x1f - sustain |= (sustain + 1) & 0x10; - sustainLevel = sustain << (ENV_BITS - 5); - - if(change & 0x0f) - UpdateRelease(chip); - } - - void Operator::WriteE0(const Chip *chip, Bit8u val) - { - if(!(regE0 ^ val)) - return; - - //in opl3 mode you can always selet 7 waveforms regardless of waveformselect - Bit8u waveForm = val & ((0x3 & chip->waveFormMask) | (0x7 & chip->opl3Active)); - regE0 = val; - #if ( DBOPL_WAVE == WAVE_HANDLER ) - waveHandler = WaveHandlerTable[ waveForm ]; - #else - waveBase = WaveTable + WaveBaseTable[ waveForm ]; - waveStart = WaveStartTable[ waveForm ] << WAVE_SH; - waveMask = WaveMaskTable[ waveForm ]; - #endif - } - - INLINE void Operator::SetState(Bit8u s) - { - state = s; - volHandler = VolumeHandlerTable[ s ]; - } - - INLINE bool Operator::Silent() const - { - if(!ENV_SILENT(totalLevel + volume)) - return false; - - if(!(rateZero & (1 << state))) - return false; - - return true; - } - - INLINE void Operator::Prepare(const Chip *chip) - { - currentLevel = totalLevel + (chip->tremoloValue & tremoloMask); - waveCurrent = waveAdd; - - if(vibStrength >> chip->vibratoShift) - { - Bit32s add = vibrato >> chip->vibratoShift; - //Sign extend over the shift value - Bit32s neg = chip->vibratoSign; - //Negate the add with -1 or 0 - add = (add ^ neg) - neg; - waveCurrent += add; - } - } - - void Operator::KeyOn(Bit8u mask) - { - if(!keyOn) - { - //Restart the frequency generator - #if ( DBOPL_WAVE > WAVE_HANDLER ) - waveIndex = waveStart; - #else - waveIndex = 0; - #endif - rateIndex = 0; - SetState(ATTACK); - } - - keyOn |= mask; - } - - void Operator::KeyOff(Bit8u mask) - { - keyOn &= ~mask; - - if(!keyOn) - { - if(state != OFF) - SetState(RELEASE); - } - } - - INLINE Bits Operator::GetWave(Bitu index, Bitu vol) - { - #if ( DBOPL_WAVE == WAVE_HANDLER ) - return waveHandler(index, vol << (3 - ENV_EXTRA)); - #elif ( DBOPL_WAVE == WAVE_TABLEMUL ) - return (waveBase[ index & waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH; - #elif ( DBOPL_WAVE == WAVE_TABLELOG ) - Bit32s wave = waveBase[ index & waveMask ]; - Bit32u total = (wave & 0x7fff) + vol << (3 - ENV_EXTRA); - Bit32s sig = ExpTable[ total & 0xff ]; - Bit32u exp = total >> 8; - Bit32s neg = wave >> 16; - return ((sig ^ neg) - neg) >> exp; - #else -#error "No valid wave routine" - #endif - } - - Bits INLINE Operator::GetSample(Bits modulation) - { - Bitu vol = ForwardVolume(); - - if(ENV_SILENT(vol)) - { - //Simply forward the wave - waveIndex += waveCurrent; - return 0; - } - else - { - Bitu index = ForwardWave(); - index += modulation; - return GetWave(index, vol); - } - } - - Operator::Operator() - { - chanData = 0; - freqMul = 0; - waveIndex = 0; - waveAdd = 0; - waveCurrent = 0; - keyOn = 0; - ksr = 0; - reg20 = 0; - reg40 = 0; - reg60 = 0; - reg80 = 0; - regE0 = 0; - SetState(OFF); - rateZero = (1 << OFF); - sustainLevel = ENV_MAX; - currentLevel = ENV_MAX; - totalLevel = ENV_MAX; - volume = ENV_MAX; - releaseAdd = 0; - } - - /* - Channel - */ - - Channel::Channel() - { - old[0] = old[1] = 0; - chanData = 0; - regB0 = 0; - regC0 = 0; - maskLeft = -1; - maskRight = -1; - feedback = 31; - fourMask = 0; - synthHandler = &Channel::BlockTemplate< sm2FM >; - } - - void Channel::SetChanData(const Chip *chip, Bit32u data) - { - Bit32u change = chanData ^ data; - chanData = data; - Op(0)->chanData = data; - Op(1)->chanData = data; - //Since a frequency update triggered this, always update frequency - Op(0)->UpdateFrequency(); - Op(1)->UpdateFrequency(); - - if(change & (0xff << SHIFT_KSLBASE)) - { - Op(0)->UpdateAttenuation(); - Op(1)->UpdateAttenuation(); - } - - if(change & (0xff << SHIFT_KEYCODE)) - { - Op(0)->UpdateRates(chip); - Op(1)->UpdateRates(chip); - } - } - - void Channel::UpdateFrequency(const Chip *chip, Bit8u fourOp) - { - //Extrace the frequency bits - Bit32u data = chanData & 0xffff; - Bit32u kslBase = KslTable[ data >> 6 ]; - Bit32u keyCode = (data & 0x1c00) >> 9; - - if(chip->reg08 & 0x40) - { - keyCode |= (data & 0x100) >> 8; /* notesel == 1 */ - } - else - { - keyCode |= (data & 0x200) >> 9; /* notesel == 0 */ - } - - //Add the keycode and ksl into the highest bits of chanData - data |= (keyCode << SHIFT_KEYCODE) | (kslBase << SHIFT_KSLBASE); - (this + 0)->SetChanData(chip, data); - - if(fourOp & 0x3f) - (this + 1)->SetChanData(chip, data); - } - - void Channel::WriteA0(const Chip *chip, Bit8u val) - { - Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask; - - //Don't handle writes to silent fourop channels - if(fourOp > 0x80) - return; - - Bit32u change = (chanData ^ val) & 0xff; - - if(change) - { - chanData ^= change; - UpdateFrequency(chip, fourOp); - } - } - - void Channel::WriteB0(const Chip *chip, Bit8u val) - { - Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask; - - //Don't handle writes to silent fourop channels - if(fourOp > 0x80) - return; - - Bitu change = (chanData ^ (val << 8)) & 0x1f00; - - if(change) - { - chanData ^= change; - UpdateFrequency(chip, fourOp); - } - - //Check for a change in the keyon/off state - if(!((val ^ regB0) & 0x20)) - return; - - regB0 = val; - - if(val & 0x20) - { - Op(0)->KeyOn(0x1); - Op(1)->KeyOn(0x1); - - if(fourOp & 0x3f) - { - (this + 1)->Op(0)->KeyOn(1); - (this + 1)->Op(1)->KeyOn(1); - } - } - else - { - Op(0)->KeyOff(0x1); - Op(1)->KeyOff(0x1); - - if(fourOp & 0x3f) - { - (this + 1)->Op(0)->KeyOff(1); - (this + 1)->Op(1)->KeyOff(1); - } - } - } - - void Channel::WriteC0(const Chip *chip, Bit8u val) - { - Bit8u change = val ^ regC0; - - if(!change) - return; - - regC0 = val; - feedback = (val >> 1) & 7; - - if(feedback) - { - //We shift the input to the right 10 bit wave index value - feedback = 9 - feedback; - } - else - feedback = 31; - - //Select the new synth mode - if(chip->opl3Active) - { - //4-op mode enabled for this channel - if((chip->reg104 & fourMask) & 0x3f) - { - Channel *chan0, *chan1; - - //Check if it's the 2nd channel in a 4-op - if(!(fourMask & 0x80)) - { - chan0 = this; - chan1 = this + 1; - } - else - { - chan0 = this - 1; - chan1 = this; - } - - Bit8u synth = ((chan0->regC0 & 1) << 0) | ((chan1->regC0 & 1) << 1); - - switch(synth) - { - case 0: - chan0->synthHandler = &Channel::BlockTemplate< sm3FMFM >; - break; - - case 1: - chan0->synthHandler = &Channel::BlockTemplate< sm3AMFM >; - break; - - case 2: - chan0->synthHandler = &Channel::BlockTemplate< sm3FMAM >; - break; - - case 3: - chan0->synthHandler = &Channel::BlockTemplate< sm3AMAM >; - break; - } - - //Disable updating percussion channels - } - else if((fourMask & 0x40) && (chip->regBD & 0x20)) - { - //Regular dual op, am or fm - } - else if(val & 1) - synthHandler = &Channel::BlockTemplate< sm3AM >; - else - synthHandler = &Channel::BlockTemplate< sm3FM >; - - maskLeft = (val & 0x10) ? -1 : 0; - maskRight = (val & 0x20) ? -1 : 0; - //opl2 active - } - else - { - //Disable updating percussion channels - if((fourMask & 0x40) && (chip->regBD & 0x20)) - { - //Regular dual op, am or fm - } - else if(val & 1) - synthHandler = &Channel::BlockTemplate< sm2AM >; - else - synthHandler = &Channel::BlockTemplate< sm2FM >; - } - } - - void Channel::ResetC0(const Chip *chip) - { - Bit8u val = regC0; - regC0 ^= 0xff; - WriteC0(chip, val); - } - - template< bool opl3Mode> - INLINE void Channel::GeneratePercussion(Chip *chip, Bit32s *output) - { - Channel *chan = this; - //BassDrum - Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback; - old[0] = old[1]; - old[1] = Op(0)->GetSample(mod); - - //When bassdrum is in AM mode first operator is ignoed - if(chan->regC0 & 1) - mod = 0; - else - mod = old[0]; - - Bit32s sample = Op(1)->GetSample(mod); - //Precalculate stuff used by other outputs - Bit32u noiseBit = chip->ForwardNoise() & 0x1; - Bit32u c2 = Op(2)->ForwardWave(); - Bit32u c5 = Op(5)->ForwardWave(); - Bit32u phaseBit = (((c2 & 0x88) ^ ((c2 << 5) & 0x80)) | ((c5 ^ (c5 << 2)) & 0x20)) ? 0x02 : 0x00; - //Hi-Hat - Bit32u hhVol = Op(2)->ForwardVolume(); - - if(!ENV_SILENT(hhVol)) - { - Bit32u hhIndex = (phaseBit << 8) | (0x34 << (phaseBit ^ (noiseBit << 1))); - sample += Op(2)->GetWave(hhIndex, hhVol); - } - - //Snare Drum - Bit32u sdVol = Op(3)->ForwardVolume(); - - if(!ENV_SILENT(sdVol)) - { - Bit32u sdIndex = (0x100 + (c2 & 0x100)) ^ (noiseBit << 8); - sample += Op(3)->GetWave(sdIndex, sdVol); - } - - //Tom-tom - sample += Op(4)->GetSample(0); - //Top-Cymbal - Bit32u tcVol = Op(5)->ForwardVolume(); - - if(!ENV_SILENT(tcVol)) - { - Bit32u tcIndex = (1 + phaseBit) << 8; - sample += Op(5)->GetWave(tcIndex, tcVol); - } - - sample <<= 1; - - if(opl3Mode) - { - output[0] += sample; - output[1] += sample; - } - else - output[0] += sample; - } - - template - Channel *Channel::BlockTemplate(Chip *chip, Bit32u samples, Bit32s *output) - { - switch(mode) - { - case sm2AM: - case sm3AM: - if(Op(0)->Silent() && Op(1)->Silent()) - { - old[0] = old[1] = 0; - return (this + 1); - } - - break; - - case sm2FM: - case sm3FM: - if(Op(1)->Silent()) - { - old[0] = old[1] = 0; - return (this + 1); - } - - break; - - case sm3FMFM: - if(Op(3)->Silent()) - { - old[0] = old[1] = 0; - return (this + 2); - } - - break; - - case sm3AMFM: - if(Op(0)->Silent() && Op(3)->Silent()) - { - old[0] = old[1] = 0; - return (this + 2); - } - - break; - - case sm3FMAM: - if(Op(1)->Silent() && Op(3)->Silent()) - { - old[0] = old[1] = 0; - return (this + 2); - } - - break; - - case sm3AMAM: - if(Op(0)->Silent() && Op(2)->Silent() && Op(3)->Silent()) - { - old[0] = old[1] = 0; - return (this + 2); - } - - break; - - default: - break; - } - - //Init the operators with the the current vibrato and tremolo values - Op(0)->Prepare(chip); - Op(1)->Prepare(chip); - - if(mode > sm4Start) - { - Op(2)->Prepare(chip); - Op(3)->Prepare(chip); - } - - if(mode > sm6Start) - { - Op(4)->Prepare(chip); - Op(5)->Prepare(chip); - } - - for(Bitu i = 0; i < samples; i++) - { - //Early out for percussion handlers - if(mode == sm2Percussion) - { - GeneratePercussion(chip, output + i); - continue; //Prevent some unitialized value bitching - } - else if(mode == sm3Percussion) - { - GeneratePercussion(chip, output + i * 2); - continue; //Prevent some unitialized value bitching - } - - //Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise - Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback; - old[0] = old[1]; - old[1] = Op(0)->GetSample(mod); - Bit32s sample; - Bit32s out0 = old[0]; - - if(mode == sm2AM || mode == sm3AM) - sample = out0 + Op(1)->GetSample(0); - else if(mode == sm2FM || mode == sm3FM) - sample = Op(1)->GetSample(out0); - else if(mode == sm3FMFM) - { - Bits next = Op(1)->GetSample(out0); - next = Op(2)->GetSample(next); - sample = Op(3)->GetSample(next); - } - else if(mode == sm3AMFM) - { - sample = out0; - Bits next = Op(1)->GetSample(0); - next = Op(2)->GetSample(next); - sample += Op(3)->GetSample(next); - } - else if(mode == sm3FMAM) - { - sample = Op(1)->GetSample(out0); - Bits next = Op(2)->GetSample(0); - sample += Op(3)->GetSample(next); - } - else if(mode == sm3AMAM) - { - sample = out0; - Bits next = Op(1)->GetSample(0); - sample += Op(2)->GetSample(next); - sample += Op(3)->GetSample(0); - } - - switch(mode) - { - case sm2AM: - case sm2FM: - output[ i ] += sample; - break; - - case sm3AM: - case sm3FM: - case sm3FMFM: - case sm3AMFM: - case sm3FMAM: - case sm3AMAM: - output[ i * 2 + 0 ] += sample & maskLeft; - output[ i * 2 + 1 ] += sample & maskRight; - break; - - default: - break; - } - } - - switch(mode) - { - case sm2AM: - case sm2FM: - case sm3AM: - case sm3FM: - return (this + 1); - - case sm3FMFM: - case sm3AMFM: - case sm3FMAM: - case sm3AMAM: - return(this + 2); - - case sm2Percussion: - case sm3Percussion: - return(this + 3); - } - - return 0; - } - - /* - Chip - */ - - Chip::Chip() - { - reg08 = 0; - reg04 = 0; - regBD = 0; - reg104 = 0; - opl3Active = 0; - //Extra zeros! - vibratoIndex = 0; - tremoloIndex = 0; - vibratoSign = 0; - vibratoShift = 0; - tremoloValue = 0; - vibratoStrength = 0; - tremoloStrength = 0; - waveFormMask = 0; - lfoCounter = 0; - lfoAdd = 0; - noiseCounter = 0; - noiseAdd = 0; - noiseValue = 0; - memset(freqMul, 0, sizeof(Bit32u) * 16); - memset(linearRates, 0, sizeof(Bit32u) * 76); - memset(attackRates, 0, sizeof(Bit32u) * 76); - } - - INLINE Bit32u Chip::ForwardNoise() - { - noiseCounter += noiseAdd; - Bitu count = noiseCounter >> LFO_SH; - noiseCounter &= WAVE_MASK; - - for(; count > 0; --count) - { - //Noise calculation from mame - noiseValue ^= (0x800302) & (0 - (noiseValue & 1)); - noiseValue >>= 1; - } - - return noiseValue; - } - - INLINE Bit32u Chip::ForwardLFO(Bit32u samples) - { - //Current vibrato value, runs 4x slower than tremolo - vibratoSign = (VibratoTable[ vibratoIndex >> 2]) >> 7; - vibratoShift = (VibratoTable[ vibratoIndex >> 2] & 7) + vibratoStrength; - tremoloValue = TremoloTable[ tremoloIndex ] >> tremoloStrength; - //Check hom many samples there can be done before the value changes - Bit32u todo = LFO_MAX - lfoCounter; - Bit32u count = (todo + lfoAdd - 1) / lfoAdd; - - if(count > samples) - { - count = samples; - lfoCounter += count * lfoAdd; - } - else - { - lfoCounter += count * lfoAdd; - lfoCounter &= (LFO_MAX - 1); - //Maximum of 7 vibrato value * 4 - vibratoIndex = (vibratoIndex + 1) & 31; - - //Clip tremolo to the the table size - if(tremoloIndex + 1 < TREMOLO_TABLE) - ++tremoloIndex; - else - tremoloIndex = 0; - } - - return count; - } - - - void Chip::WriteBD(Bit8u val) - { - Bit8u change = regBD ^ val; - - if(!change) - return; - - regBD = val; - //TODO could do this with shift and xor? - vibratoStrength = (val & 0x40) ? 0x00 : 0x01; - tremoloStrength = (val & 0x80) ? 0x00 : 0x02; - - if(val & 0x20) - { - //Drum was just enabled, make sure channel 6 has the right synth - if(change & 0x20) - { - if(opl3Active) - chan[6].synthHandler = &Channel::BlockTemplate< sm3Percussion >; - else - chan[6].synthHandler = &Channel::BlockTemplate< sm2Percussion >; - } - - //Bass Drum - if(val & 0x10) - { - chan[6].op[0].KeyOn(0x2); - chan[6].op[1].KeyOn(0x2); - } - else - { - chan[6].op[0].KeyOff(0x2); - chan[6].op[1].KeyOff(0x2); - } - - //Hi-Hat - if(val & 0x1) - chan[7].op[0].KeyOn(0x2); - else - chan[7].op[0].KeyOff(0x2); - - //Snare - if(val & 0x8) - chan[7].op[1].KeyOn(0x2); - else - chan[7].op[1].KeyOff(0x2); - - //Tom-Tom - if(val & 0x4) - chan[8].op[0].KeyOn(0x2); - else - chan[8].op[0].KeyOff(0x2); - - //Top Cymbal - if(val & 0x2) - chan[8].op[1].KeyOn(0x2); - else - chan[8].op[1].KeyOff(0x2); - - //Toggle keyoffs when we turn off the percussion - } - else if(change & 0x20) - { - //Trigger a reset to setup the original synth handler - chan[6].ResetC0(this); - chan[6].op[0].KeyOff(0x2); - chan[6].op[1].KeyOff(0x2); - chan[7].op[0].KeyOff(0x2); - chan[7].op[1].KeyOff(0x2); - chan[8].op[0].KeyOff(0x2); - chan[8].op[1].KeyOff(0x2); - } - } - - -#define REGOP( _FUNC_ ) \ - index = ( ( reg >> 3) & 0x20 ) | ( reg & 0x1f ); \ - if ( OpOffsetTable[ index ] ) { \ - Operator* regOp = (Operator*)( ((char *)this ) + OpOffsetTable[ index ] ); \ - regOp->_FUNC_( this, val ); \ - } - -#define REGCHAN( _FUNC_ ) \ - index = ( ( reg >> 4) & 0x10 ) | ( reg & 0xf ); \ - if ( ChanOffsetTable[ index ] ) { \ - Channel* regChan = (Channel*)( ((char *)this ) + ChanOffsetTable[ index ] ); \ - regChan->_FUNC_( this, val ); \ - } - - void Chip::WriteReg(Bit32u reg, Bit8u val) - { - Bitu index = 0; - - switch((reg & 0xf0) >> 4) - { - case 0x00 >> 4: - if(reg == 0x01) - waveFormMask = (val & 0x20) ? 0x7 : 0x0; - else if(reg == 0x104) - { - //Only detect changes in lowest 6 bits - if(!((reg104 ^ val) & 0x3f)) - return; - - //Always keep the highest bit enabled, for checking > 0x80 - reg104 = 0x80 | (val & 0x3f); - } - else if(reg == 0x105) - { - //MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register - if(!((opl3Active ^ val) & 1)) - return; - - opl3Active = (val & 1) ? 0xff : 0; - - //Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers - for(int i = 0; i < 18; i++) - chan[i].ResetC0(this); - } - else if(reg == 0x08) - reg08 = val; - - case 0x10 >> 4: - break; - - case 0x20 >> 4: - case 0x30 >> 4: - REGOP(Write20); - break; - - case 0x40 >> 4: - case 0x50 >> 4: - REGOP(Write40); - break; - - case 0x60 >> 4: - case 0x70 >> 4: - REGOP(Write60); - break; - - case 0x80 >> 4: - case 0x90 >> 4: - REGOP(Write80); - break; - - case 0xa0 >> 4: - REGCHAN(WriteA0); - break; - - case 0xb0 >> 4: - if(reg == 0xbd) - WriteBD(val); - else - REGCHAN(WriteB0); - - break; - - case 0xc0 >> 4: - REGCHAN(WriteC0); - - case 0xd0 >> 4: - break; - - case 0xe0 >> 4: - case 0xf0 >> 4: - REGOP(WriteE0); - break; - } - } - - - Bit32u Chip::WriteAddr(Bit32u port, Bit8u val) - { - switch(port & 3) - { - case 0: - return val; - - case 2: - if(opl3Active || (val == 0x05)) - return 0x100 | val; - else - return val; - } - - return 0; - } - - void Chip::GenerateBlock2(Bitu total, Bit32s *output) - { - while(total > 0) - { - Bit32u samples = ForwardLFO(total); - memset(output, 0, sizeof(Bit32s) * samples); - int count = 0; - - for(Channel *ch = chan; ch < chan + 9;) - { - count++; - ch = (ch->*(ch->synthHandler))(this, samples, output); - } - - total -= samples; - output += samples; - } - } - - void Chip::GenerateBlock3(Bitu total, Bit32s *output) - { - while(total > 0) - { - Bit32u samples = ForwardLFO((Bit32u)total); - memset(output, 0, sizeof(Bit32s) * samples * 2); - int count = 0; - - for(Channel *ch = chan; ch < chan + 18;) - { - count++; - ch = (ch->*(ch->synthHandler))(this, samples, output); - } - - total -= samples; - output += samples * 2; - } - } - - void Chip::GenerateBlock2_Mix(Bitu total, Bit32s *output) - { - while(total > 0) - { - Bit32u samples = ForwardLFO((Bit32u)total); - int count = 0; - for(Channel *ch = chan; ch < chan + 9;) - { - count++; - ch = (ch->*(ch->synthHandler))(this, samples, output); - } - - total -= samples; - output += samples; - } - } - - void Chip::GenerateBlock3_Mix(Bitu total, Bit32s *output) - { - while(total > 0) - { - Bit32u samples = ForwardLFO(total); - int count = 0; - for(Channel *ch = chan; ch < chan + 18;) - { - count++; - ch = (ch->*(ch->synthHandler))(this, samples, output); - } - total -= samples; - output += samples * 2; - } - } - - void Chip::Setup(Bit32u rate) - { - double original = OPLRATE; - // double original = rate; - double scale = original / (double)rate; - //Noise counter is run at the same precision as general waves - noiseAdd = (Bit32u)(0.5 + scale * (1 << LFO_SH)); - noiseCounter = 0; - noiseValue = 1; //Make sure it triggers the noise xor the first time - //The low frequency oscillation counter - //Every time his overflows vibrato and tremoloindex are increased - lfoAdd = (Bit32u)(0.5 + scale * (1 << LFO_SH)); - lfoCounter = 0; - vibratoIndex = 0; - tremoloIndex = 0; - //With higher octave this gets shifted up - //-1 since the freqCreateTable = *2 - #ifdef WAVE_PRECISION - double freqScale = (1 << 7) * scale * (1 << (WAVE_SH - 1 - 10)); - - for(int i = 0; i < 16; i++) - freqMul[i] = (Bit32u)(0.5 + freqScale * FreqCreateTable[ i ]); - - #else - Bit32u freqScale = (Bit32u)(0.5 + scale * (1 << (WAVE_SH - 1 - 10))); - - for(int i = 0; i < 16; i++) - freqMul[i] = freqScale * FreqCreateTable[ i ]; - - #endif - - //-3 since the real envelope takes 8 steps to reach the single value we supply - for(Bit8u i = 0; i < 76; i++) - { - Bit8u index, shift; - EnvelopeSelect(i, index, shift); - linearRates[i] = (Bit32u)(scale * (EnvelopeIncreaseTable[ index ] << (RATE_SH + ENV_EXTRA - shift - 3))); - } - - if(rate == 48000) - { - /* BISQWIT ADD: Use precalculated table for this common sample-rate. - * Because the actual generation code, below, is MOLASSES SLOW on DOS. - */ - static const Bit32u precalculated_table[62] = - { - 2152, 2700, 3228, 3712, 4304, 5399, 6456, 7424, 8608, 10799, 12912, 14849, 17216, 21598, - 25824, 29698, 34432, 43196, 51650, 59398, 68864, 86392, 103310, 118795, 137746, 172847, - 206619, 237693, 275559, 345774, 413238, 475500, 543030, 678787, 814545, 950302, 1086060, - 1357575, 1629090, 1900605, 2172120, 2715151, 3258181, 3801211, 4344241, 5430302, - 6516362, 7602423, 8688483, 10860604, 13032725, 15204846, 17376967, 21721209, 26065451, - 30409693, 34753934, 43442418, 52130902, 60819386, 69507869, 69507869 - }; - - for(Bit8u i = 0; i < 62; i++) - attackRates[i] = precalculated_table[i]; - } - else if(rate == 44100) - { - static const Bit32u precalculated_table[62] = - { - 2342, 2939, 3513, 4040, 4685, 5877, 7027, 8081, 9369, 11754, 14054, 16162, 18738, 23508, - 28108, 32325, 37478, 47018, 56219, 64649, 74965, 94044, 112448, 129292, 149929, 188132, - 224945, 258713, 300002, 376263, 449999, 517550, 591053, 738816, 886579, 1034343, 1182106, - 1477633, 1773159, 2068686, 2364213, 2955266, 3546319, 4137373, 4728426, 5910533, - 7092639, 8274746, 9456853, 11821066, 14185279, 16549492, 18913706, 23642132, 28370559, - 33098985, 37827412, 47284265, 56741118, 66197971, 75654824, 75654824 - }; - - for(Bit8u i = 0; i < 62; i++) - attackRates[i] = precalculated_table[i]; - } - else if(rate == 22050) - { - static const Bit32u precalculated_table[62] = - { - 4685, 5877, 7027, 8081, 9369, 11754, 14054, 16162, 18738, 23508, 28108, 32325, 37478, - 47018, 56219, 64649, 74965, 94044, 112448, 129292, 149929, 188132, 224945, 258713, 300002, - 376263, 449999, 517550, 591053, 738816, 886579, 1034343, 1182106, 1477633, 1773159, - 2068686, 2364213, 2955266, 3546319, 4137373, 4728426, 5910533, 7092639, 8274746, - 9456853, 11821066, 14185279, 16549492, 18913706, 23642132, 28370559, 33098985, - 37827412, 47284265, 56741118, 66197971, 75654824, 94568530, 113482236, 132395942, - 151309648, 151309648 - }; - - for(Bit8u i = 0; i < 62; i++) - attackRates[i] = precalculated_table[i]; - } - //Generate the best matching attack rate - else for(Bit8u i = 0; i < 62; i++) - { - Bit8u index, shift; - EnvelopeSelect(i, index, shift); - //Original amount of samples the attack would take - Bit32s original = (Bit32u)((AttackSamplesTable[ index ] << shift) / scale); - Bit32s guessAdd = (Bit32u)(scale * (EnvelopeIncreaseTable[ index ] << (RATE_SH - shift - 3))); - Bit32s bestAdd = guessAdd; - Bit32u bestDiff = 1 << 30; - - for(Bit32u passes = 0; passes < 16; passes ++) - { - Bit32s volume = ENV_MAX; - Bit32s samples = 0; - Bit32u count = 0; - - while(volume > 0 && samples < original * 2) - { - count += guessAdd; - Bit32s change = count >> RATE_SH; - count &= RATE_MASK; - - if(GCC_UNLIKELY(change)) // less than 1 % - volume += (~volume * change) >> 3; - - samples++; - } - - Bit32s diff = original - samples; - Bit32u lDiff = labs(diff); - - //Init last on first pass - if(lDiff < bestDiff) - { - bestDiff = lDiff; - bestAdd = guessAdd; - - if(!bestDiff) - break; - } - - //Below our target - if(diff < 0) - { - //Better than the last time - Bit32s mul = ((original - diff) << 12) / original; - guessAdd = ((guessAdd * mul) >> 12); - guessAdd++; - } - else if(diff > 0) - { - Bit32s mul = ((original - diff) << 12) / original; - guessAdd = (guessAdd * mul) >> 12; - guessAdd--; - } - } - - attackRates[i] = bestAdd; - } - - /*fprintf(stderr, "attack rate table: "); - for ( Bit8u i = 0; i < 62; i++ ) - fprintf(stderr, ",%u", attackRates[i]); - fprintf(stderr, "\n");*/ - - for(Bit8u i = 62; i < 76; i++) - { - //This should provide instant volume maximizing - attackRates[i] = 8 << RATE_SH; - } - - //Setup the channels with the correct four op flags - //Channels are accessed through a table so they appear linear here - chan[ 0].fourMask = 0x00 | (1 << 0); - chan[ 1].fourMask = 0x80 | (1 << 0); - chan[ 2].fourMask = 0x00 | (1 << 1); - chan[ 3].fourMask = 0x80 | (1 << 1); - chan[ 4].fourMask = 0x00 | (1 << 2); - chan[ 5].fourMask = 0x80 | (1 << 2); - chan[ 9].fourMask = 0x00 | (1 << 3); - chan[10].fourMask = 0x80 | (1 << 3); - chan[11].fourMask = 0x00 | (1 << 4); - chan[12].fourMask = 0x80 | (1 << 4); - chan[13].fourMask = 0x00 | (1 << 5); - chan[14].fourMask = 0x80 | (1 << 5); - //mark the percussion channels - chan[ 6].fourMask = 0x40; - chan[ 7].fourMask = 0x40; - chan[ 8].fourMask = 0x40; - //Clear Everything in opl3 mode - WriteReg(0x105, 0x1); - - for(int i = 0; i < 512; i++) - { - if(i == 0x105) - continue; - - WriteReg(i, 0xff); - WriteReg(i, 0x0); - } - - WriteReg(0x105, 0x0); - - //Clear everything in opl2 mode - for(int i = 0; i < 255; i++) - { - WriteReg(i, 0xff); - WriteReg(i, 0x0); - } - } - - static bool doneTables = false; - void InitTables(void) - { - if(doneTables) - return; - - doneTables = true; - #if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG ) - - //Exponential volume table, same as the real adlib - for(int i = 0; i < 256; i++) - { - //Save them in reverse - ExpTable[i] = (int)(0.5 + (pow(2.0, (255 - i) * (1.0 / 256)) - 1) * 1024); - ExpTable[i] += 1024; //or remove the -1 oh well :) - //Preshift to the left once so the final volume can shift to the right - ExpTable[i] *= 2; - } - - #endif - #if ( DBOPL_WAVE == WAVE_HANDLER ) - - //Add 0.5 for the trunc rounding of the integer cast - //Do a PI sinetable instead of the original 0.5 PI - for(int i = 0; i < 512; i++) - SinTable[i] = (Bit16s)(0.5 - log10(sin((i + 0.5) * (PI / 512.0))) / log10(2.0) * 256); - - #endif - #if ( DBOPL_WAVE == WAVE_TABLEMUL ) - - //Multiplication based tables - for(int i = 0; i < 384; i++) - { - int s = i * 8; - //TODO maybe keep some of the precision errors of the original table? - double val = (0.5 + (pow(2.0, -1.0 + (255 - s) * (1.0 / 256))) * (1 << MUL_SH)); - MulTable[i] = (Bit16u)(val); - } - - //Sine Wave Base - for(int i = 0; i < 512; i++) - { - WaveTable[ 0x0200 + i ] = (Bit16s)(sin((i + 0.5) * (PI / 512.0)) * 4084); - WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ]; - } - - //Exponential wave - for(int i = 0; i < 256; i++) - { - WaveTable[ 0x700 + i ] = (Bit16s)(0.5 + (pow(2.0, -1.0 + (255 - i * 8) * (1.0 / 256))) * 4085); - WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ]; - } - - #endif - #if ( DBOPL_WAVE == WAVE_TABLELOG ) - - //Sine Wave Base - for(int i = 0; i < 512; i++) - { - WaveTable[ 0x0200 + i ] = (Bit16s)(0.5 - log10(sin((i + 0.5) * (PI / 512.0))) / log10(2.0) * 256); - WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i]; - } - - //Exponential wave - for(int i = 0; i < 256; i++) - { - WaveTable[ 0x700 + i ] = i * 8; - WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8; - } - - #endif - // | |//\\|____|WAV7|//__|/\ |____|/\/\| - // |\\//| | |WAV7| | \/| | | - // |06 |0126|27 |7 |3 |4 |4 5 |5 | - #if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL )) - - for(int i = 0; i < 256; i++) - { - //Fill silence gaps - WaveTable[ 0x400 + i ] = WaveTable[0]; - WaveTable[ 0x500 + i ] = WaveTable[0]; - WaveTable[ 0x900 + i ] = WaveTable[0]; - WaveTable[ 0xc00 + i ] = WaveTable[0]; - WaveTable[ 0xd00 + i ] = WaveTable[0]; - //Replicate sines in other pieces - WaveTable[ 0x800 + i ] = WaveTable[ 0x200 + i ]; - //double speed sines - WaveTable[ 0xa00 + i ] = WaveTable[ 0x200 + i * 2 ]; - WaveTable[ 0xb00 + i ] = WaveTable[ 0x000 + i * 2 ]; - WaveTable[ 0xe00 + i ] = WaveTable[ 0x200 + i * 2 ]; - WaveTable[ 0xf00 + i ] = WaveTable[ 0x200 + i * 2 ]; - } - - #endif - - //Create the ksl table - for(int oct = 0; oct < 8; oct++) - { - int base = oct * 8; - - for(int i = 0; i < 16; i++) - { - int val = base - KslCreateTable[i]; - - if(val < 0) - val = 0; - - //*4 for the final range to match attenuation range - KslTable[ oct * 16 + i ] = val * 4; - } - } - - //Create the Tremolo table, just increase and decrease a triangle wave - for(Bit8u i = 0; i < TREMOLO_TABLE / 2; i++) - { - Bit8u val = i << ENV_EXTRA; - TremoloTable[i] = val; - TremoloTable[TREMOLO_TABLE - 1 - i] = val; - } - - //Create a table with offsets of the channels from the start of the chip - DBOPL::Chip *chip = 0; - - for(Bitu i = 0; i < 32; i++) - { - Bitu index = i & 0xf; - - if(index >= 9) - { - ChanOffsetTable[i] = 0; - continue; - } - - //Make sure the four op channels follow eachother - if(index < 6) - index = (index % 3) * 2 + (index / 3); - - //Add back the bits for highest ones - if(i >= 16) - index += 9; - - Bitu blah = reinterpret_cast(&(chip->chan[ index ])); - ChanOffsetTable[i] = blah; - } - - //Same for operators - for(Bitu i = 0; i < 64; i++) - { - if(i % 8 >= 6 || ((i / 8) % 4 == 3)) - { - OpOffsetTable[i] = 0; - continue; - } - - Bitu chNum = (i / 8) * 3 + (i % 8) % 3; - - //Make sure we use 16 and up for the 2nd range to match the chanoffset gap - if(chNum >= 12) - chNum += 16 - 12; - - Bitu opNum = (i % 8) / 3; - DBOPL::Channel *chan = 0; - Bitu blah = reinterpret_cast(&(chan->op[opNum])); - OpOffsetTable[i] = ChanOffsetTable[ chNum ] + blah; - } - - #if 0 - - //Stupid checks if table's are correct - for(Bitu i = 0; i < 18; i++) - { - Bit32u find = (Bit16u)(&(chip->chan[ i ])); - - for(Bitu c = 0; c < 32; c++) - { - if(ChanOffsetTable[c] == find) - { - find = 0; - break; - } - } - - if(find) - find = find; - } - - for(Bitu i = 0; i < 36; i++) - { - Bit32u find = (Bit16u)(&(chip->chan[ i / 2 ].op[i % 2])); - - for(Bitu c = 0; c < 64; c++) - { - if(OpOffsetTable[c] == find) - { - find = 0; - break; - } - } - - if(find) - find = find; - } - - #endif - } - - Bit32u Handler::WriteAddr(Bit32u port, Bit8u val) - { - return chip.WriteAddr(port, val); - } - void Handler::WriteReg(Bit32u addr, Bit8u val) - { - chip.WriteReg(addr, val); - } - - void Handler::Generate(void(*AddSamples_m32)(Bitu, Bit32s *), - void(*AddSamples_s32)(Bitu, Bit32s *), - Bitu samples) - { - Bit32s buffer[ 512 * 2 ]; - - if(GCC_UNLIKELY(samples > 512)) - samples = 512; - - if(!chip.opl3Active) - { - chip.GenerateBlock2(samples, buffer); - AddSamples_m32(samples, buffer); - } - else - { - chip.GenerateBlock3(samples, buffer); - AddSamples_s32(samples, buffer); - } - } - - void Handler::GenerateArr(Bit32s *out, Bitu *samples) - { - if(GCC_UNLIKELY(*samples > 512)) - *samples = 512; - - if(!chip.opl3Active) - chip.GenerateBlock2(*samples, out); - else - chip.GenerateBlock3(*samples, out); - } - - void Handler::GenerateArr(Bit32s *out, ssize_t *samples) - { - if(GCC_UNLIKELY(*samples > 512)) - *samples = 512; - - if(!chip.opl3Active) - chip.GenerateBlock2(static_cast(*samples), out); - else - chip.GenerateBlock3(static_cast(*samples), out); - } - - void Handler::GenerateArr(Bit16s *out, ssize_t *samples) - { - Bit32s out32[1024]; - if(GCC_UNLIKELY(*samples > 512)) - *samples = 512; - memset(out32, 0, sizeof(Bit32s) * 1024); - if(!chip.opl3Active) - chip.GenerateBlock2(static_cast(*samples), out32); - else - chip.GenerateBlock3(static_cast(*samples), out32); - ssize_t sz = *samples * 2; - for(ssize_t i = 0; i < sz; i++) - out[i] = static_cast(DBOPL_CLAMP(out32[i], static_cast(INT16_MIN), static_cast(INT16_MAX))); - } - - void Handler::GenerateArrMix(Bit32s *out, ssize_t *samples) - { - if(GCC_UNLIKELY(*samples > 512)) - *samples = 512; - if(!chip.opl3Active) - chip.GenerateBlock2_Mix(static_cast(*samples), out); - else - chip.GenerateBlock3_Mix(static_cast(*samples), out); - } - - void Handler::GenerateArrMix(Bit16s *out, ssize_t *samples) - { - Bit32s out32[1024]; - if(GCC_UNLIKELY(*samples > 512)) - *samples = 512; - memset(out32, 0, sizeof(Bit32s) * 1024); - if(!chip.opl3Active) - chip.GenerateBlock2(static_cast(*samples), out32); - else - chip.GenerateBlock3(static_cast(*samples), out32); - ssize_t sz = *samples * 2; - for(ssize_t i = 0; i < sz; i++) - out[i] += static_cast(DBOPL_CLAMP(out32[i], static_cast(INT16_MIN), static_cast(INT16_MAX))); - } - - - void Handler::Init(Bitu rate) - { - InitTables(); - chip.Setup((Bit32u)rate); - } - - -} //Namespace DBOPL - -#endif //ADLMIDI_USE_DOSBOX_OPL diff --git a/src/sound/adlmidi/dbopl.h b/src/sound/adlmidi/dbopl.h deleted file mode 100644 index b5b2ba10d..000000000 --- a/src/sound/adlmidi/dbopl.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2002-2010 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -/* BEGIN MIDIPLAY GLUE */ -#include -#include -typedef unsigned long Bitu; -typedef signed long Bits; -typedef unsigned Bit32u; -typedef int Bit32s; -typedef unsigned short Bit16u; -typedef signed short Bit16s; -typedef unsigned char Bit8u; -typedef signed char Bit8s; -#define INLINE inline -#ifdef _MSC_VER -#define GCC_UNLIKELY(x) (!!(x) == 0) -#define GCC_LIKELY(x) (!!(x) == 1) -#else -#define GCC_UNLIKELY(x) __builtin_expect((x),0) -#define GCC_LIKELY(x) __builtin_expect((x),1) -#endif -/* END MIDIPLAY GLUE */ - -//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume -#define WAVE_HANDLER 10 -//Use a logarithmic wavetable with an exponential table for volume -#define WAVE_TABLELOG 11 -//Use a linear wavetable with a multiply table for volume -#define WAVE_TABLEMUL 12 - -//Select the type of wave generator routine -#define DBOPL_WAVE WAVE_TABLEMUL - -#ifdef _WIN32 -# ifdef _MSC_VER -# ifdef _WIN64 -typedef __int64 ssize_t; -# else -typedef __int32 ssize_t; -# endif -# else -# ifdef _WIN64 -typedef int64_t ssize_t; -# else -typedef int32_t ssize_t; -# endif -# endif -#endif - -namespace DBOPL -{ - - struct Chip; - struct Operator; - struct Channel; - -#if (DBOPL_WAVE == WAVE_HANDLER) - typedef Bits(DB_FASTCALL *WaveHandler)(Bitu i, Bitu volume); -#endif - - typedef Bits(DBOPL::Operator::*VolumeHandler)(); - typedef Channel *(DBOPL::Channel::*SynthHandler)(Chip *chip, Bit32u samples, Bit32s *output); - - //Different synth modes that can generate blocks of data - typedef enum - { - sm2AM, - sm2FM, - sm3AM, - sm3FM, - sm4Start, - sm3FMFM, - sm3AMFM, - sm3FMAM, - sm3AMAM, - sm6Start, - sm2Percussion, - sm3Percussion - } SynthMode; - - //Shifts for the values contained in chandata variable - enum - { - SHIFT_KSLBASE = 16, - SHIFT_KEYCODE = 24 - }; - - struct Operator - { - public: - //Masks for operator 20 values - enum - { - MASK_KSR = 0x10, - MASK_SUSTAIN = 0x20, - MASK_VIBRATO = 0x40, - MASK_TREMOLO = 0x80 - }; - - typedef enum - { - OFF, - RELEASE, - SUSTAIN, - DECAY, - ATTACK - } State; - - VolumeHandler volHandler; - -#if (DBOPL_WAVE == WAVE_HANDLER) - WaveHandler waveHandler; //Routine that generate a wave -#else - Bit16s *waveBase; - Bit32u waveMask; - Bit32u waveStart; -#endif - Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index - Bit32u waveAdd; //The base frequency without vibrato - Bit32u waveCurrent; //waveAdd + vibratao - - Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this - Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove? - Bit32u vibrato; //Scaled up vibrato strength - Bit32s sustainLevel; //When stopping at sustain level stop here - Bit32s totalLevel; //totalLevel is added to every generated volume - Bit32u currentLevel; //totalLevel + tremolo - Bit32s volume; //The currently active volume - - Bit32u attackAdd; //Timers for the different states of the envelope - Bit32u decayAdd; - Bit32u releaseAdd; - Bit32u rateIndex; //Current position of the evenlope - - Bit8u rateZero; //Bits for the different states of the envelope having no changes - Bit8u keyOn; //Bitmask of different values that can generate keyon - //Registers, also used to check for changes - Bit8u reg20, reg40, reg60, reg80, regE0; - //Active part of the envelope we're in - Bit8u state; - //0xff when tremolo is enabled - Bit8u tremoloMask; - //Strength of the vibrato - Bit8u vibStrength; - //Keep track of the calculated KSR so we can check for changes - Bit8u ksr; - private: - void SetState(Bit8u s); - void UpdateAttack(const Chip *chip); - void UpdateRelease(const Chip *chip); - void UpdateDecay(const Chip *chip); - public: - void UpdateAttenuation(); - void UpdateRates(const Chip *chip); - void UpdateFrequency(); - - void Write20(const Chip *chip, Bit8u val); - void Write40(const Chip *chip, Bit8u val); - void Write60(const Chip *chip, Bit8u val); - void Write80(const Chip *chip, Bit8u val); - void WriteE0(const Chip *chip, Bit8u val); - - bool Silent() const; - void Prepare(const Chip *chip); - - void KeyOn(Bit8u mask); - void KeyOff(Bit8u mask); - - template< State state> - Bits TemplateVolume(); - - Bit32s RateForward(Bit32u add); - Bitu ForwardWave(); - Bitu ForwardVolume(); - - Bits GetSample(Bits modulation); - Bits GetWave(Bitu index, Bitu vol); - public: - Operator(); - char ____padding[5]; - }; - - struct Channel - { - Operator op[2]; - inline Operator *Op(Bitu index) - { - return &((this + (index >> 1))->op[ index & 1 ]); - } - SynthHandler synthHandler; - Bit32u chanData; //Frequency/octave and derived values - Bit32s old[2]; //Old data for feedback - - Bit8u feedback; //Feedback shift - Bit8u regB0; //Register values to check for changes - Bit8u regC0; - //This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel - Bit8u fourMask; - Bit8s maskLeft; //Sign extended values for both channel's panning - Bit8s maskRight; - - //Forward the channel data to the operators of the channel - void SetChanData(const Chip *chip, Bit32u data); - //Change in the chandata, check for new values and if we have to forward to operators - void UpdateFrequency(const Chip *chip, Bit8u fourOp); - void WriteA0(const Chip *chip, Bit8u val); - void WriteB0(const Chip *chip, Bit8u val); - void WriteC0(const Chip *chip, Bit8u val); - void ResetC0(const Chip *chip); - - //call this for the first channel - template< bool opl3Mode > - void GeneratePercussion(Chip *chip, Bit32s *output); - - //Generate blocks of data in specific modes - template - Channel *BlockTemplate(Chip *chip, Bit32u samples, Bit32s *output); - Channel(); - char ____padding[6]; - }; - - struct Chip - { - //This is used as the base counter for vibrato and tremolo - Bit32u lfoCounter; - Bit32u lfoAdd; - - - Bit32u noiseCounter; - Bit32u noiseAdd; - Bit32u noiseValue; - - //Frequency scales for the different multiplications - Bit32u freqMul[16]; - //Rates for decay and release for rate of this chip - Bit32u linearRates[76]; - //Best match attack rates for the rate of this chip - Bit32u attackRates[76]; - - //18 channels with 2 operators each - Channel chan[18]; - - Bit8u reg104; - Bit8u reg08; - Bit8u reg04; - Bit8u regBD; - Bit8u vibratoIndex; - Bit8u tremoloIndex; - Bit8s vibratoSign; - Bit8u vibratoShift; - Bit8u tremoloValue; - Bit8u vibratoStrength; - Bit8u tremoloStrength; - //Mask for allowed wave forms - Bit8u waveFormMask; - //0 or -1 when enabled - Bit8s opl3Active; - - //Return the maximum amount of samples before and LFO change - Bit32u ForwardLFO(Bit32u samples); - Bit32u ForwardNoise(); - - void WriteBD(Bit8u val); - void WriteReg(Bit32u reg, Bit8u val); - - Bit32u WriteAddr(Bit32u port, Bit8u val); - - void GenerateBlock2(Bitu samples, Bit32s *output); - void GenerateBlock3(Bitu samples, Bit32s *output); - - void GenerateBlock2_Mix(Bitu samples, Bit32s *output); - void GenerateBlock3_Mix(Bitu samples, Bit32s *output); - - void Generate(Bit32u samples); - void Setup(Bit32u r); - - Chip(); - }; - - struct Handler - { - DBOPL::Chip chip; - Bit32u WriteAddr(Bit32u port, Bit8u val); - void WriteReg(Bit32u addr, Bit8u val); - void Generate(void(*AddSamples_m32)(Bitu, Bit32s *), - void(*AddSamples_s32)(Bitu, Bit32s *), - Bitu samples); - void GenerateArr(Bit32s *out, Bitu *samples); - void GenerateArr(Bit32s *out, ssize_t *samples); - void GenerateArr(Bit16s *out, ssize_t *samples); - void GenerateArrMix(Bit32s *out, ssize_t *samples); - void GenerateArrMix(Bit16s *out, ssize_t *samples); - void Init(Bitu rate); - }; - - -} //Namespace diff --git a/src/sound/adlmidi/fraction.hpp b/src/sound/adlmidi/fraction.hpp index 1ec10ab57..1c0a38dde 100644 --- a/src/sound/adlmidi/fraction.hpp +++ b/src/sound/adlmidi/fraction.hpp @@ -4,6 +4,7 @@ #include #include + /* Fraction number handling. * Copyright (C) 1992,2001 Bisqwit (http://iki.fi/bisqwit/) */ @@ -82,6 +83,10 @@ public: self &operator= (long double orig); }; +#ifdef _MSC_VER +#pragma warning(disable:4146) +#endif + template void fraction::Optim() { @@ -110,6 +115,10 @@ void fraction::Optim() //fprintf(stderr, "result: %d/%d\n\n", nom(), denom()); } +#ifdef _MSC_VER +#pragma warning(default:4146) +#endif + template inline const fraction abs(const fraction &f) { diff --git a/src/sound/adlmidi/wopl/wopl_file.c b/src/sound/adlmidi/wopl/wopl_file.c new file mode 100644 index 000000000..25b75be53 --- /dev/null +++ b/src/sound/adlmidi/wopl/wopl_file.c @@ -0,0 +1,584 @@ +/* + * Wohlstand's OPL3 Bank File - a bank format to store OPL3 timbre data and setup + * + * Copyright (c) 2015-2018 Vitaly Novichkov + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "wopl_file.h" +#include +#include + +static const char *wopl3_magic = "WOPL3-BANK\0"; +static const char *wopli_magic = "WOPL3-INST\0"; + +static const uint16_t wopl_latest_version = 3; + +#define WOPL_INST_SIZE_V2 62 +#define WOPL_INST_SIZE_V3 66 + +static uint16_t toUint16LE(const uint8_t *arr) +{ + uint16_t num = arr[0]; + num |= ((arr[1] << 8) & 0xFF00); + return num; +} + +static uint16_t toUint16BE(const uint8_t *arr) +{ + uint16_t num = arr[1]; + num |= ((arr[0] << 8) & 0xFF00); + return num; +} + +static int16_t toSint16BE(const uint8_t *arr) +{ + int16_t num = *(const int8_t *)(&arr[0]); + num *= 1 << 8; + num |= arr[1]; + return num; +} + +static void fromUint16LE(uint16_t in, uint8_t *arr) +{ + arr[0] = in & 0x00FF; + arr[1] = (in >> 8) & 0x00FF; +} + +static void fromUint16BE(uint16_t in, uint8_t *arr) +{ + arr[1] = in & 0x00FF; + arr[0] = (in >> 8) & 0x00FF; +} + +static void fromSint16BE(int16_t in, uint8_t *arr) +{ + arr[1] = in & 0x00FF; + arr[0] = ((uint16_t)in >> 8) & 0x00FF; +} + + +WOPLFile *WOPL_Init(uint16_t melodic_banks, uint16_t percussive_banks) +{ + WOPLFile *file = NULL; + if(melodic_banks == 0) + return NULL; + if(percussive_banks == 0) + return NULL; + file = (WOPLFile*)calloc(1, sizeof(WOPLFile)); + if(!file) + return NULL; + file->banks_count_melodic = melodic_banks; + file->banks_count_percussion = percussive_banks; + file->banks_melodic = (WOPLBank*)calloc(1, sizeof(WOPLBank) * melodic_banks ); + file->banks_percussive = (WOPLBank*)calloc(1, sizeof(WOPLBank) * percussive_banks ); + return file; +} + +void WOPL_Free(WOPLFile *file) +{ + if(file) + { + if(file->banks_melodic) + free(file->banks_melodic); + if(file->banks_percussive) + free(file->banks_percussive); + free(file); + } +} + +int WOPL_BanksCmp(const WOPLFile *bank1, const WOPLFile *bank2) +{ + int res = 1; + + res &= (bank1->version == bank2->version); + res &= (bank1->opl_flags == bank2->opl_flags); + res &= (bank1->volume_model == bank2->volume_model); + res &= (bank1->banks_count_melodic == bank2->banks_count_melodic); + res &= (bank1->banks_count_percussion == bank2->banks_count_percussion); + + if(res) + { + int i; + for(i = 0; i < bank1->banks_count_melodic; i++) + res &= (memcmp(&bank1->banks_melodic[i], &bank2->banks_melodic[i], sizeof(WOPLBank)) == 0); + if(res) + { + for(i = 0; i < bank1->banks_count_percussion; i++) + res &= (memcmp(&bank1->banks_percussive[i], &bank2->banks_percussive[i], sizeof(WOPLBank)) == 0); + } + } + + return res; +} + +static void WOPL_parseInstrument(WOPLInstrument *ins, uint8_t *cursor, uint16_t version, uint8_t has_sounding_delays) +{ + int l; + strncpy(ins->inst_name, (const char*)cursor, 32); + ins->inst_name[32] = '\0'; + ins->note_offset1 = toSint16BE(cursor + 32); + ins->note_offset2 = toSint16BE(cursor + 34); + ins->midi_velocity_offset = (int8_t)cursor[36]; + ins->second_voice_detune = (int8_t)cursor[37]; + ins->percussion_key_number = cursor[38]; + ins->inst_flags = cursor[39]; + ins->fb_conn1_C0 = cursor[40]; + ins->fb_conn2_C0 = cursor[41]; + for(l = 0; l < 4; l++) + { + size_t off = 42 + (size_t)(l) * 5; + ins->operators[l].avekf_20 = cursor[off + 0]; + ins->operators[l].ksl_l_40 = cursor[off + 1]; + ins->operators[l].atdec_60 = cursor[off + 2]; + ins->operators[l].susrel_80 = cursor[off + 3]; + ins->operators[l].waveform_E0 = cursor[off + 4]; + } + if((version >= 3) && has_sounding_delays) + { + ins->delay_on_ms = toUint16BE(cursor + 62); + ins->delay_off_ms = toUint16BE(cursor + 64); + } +} + +static void WOPL_writeInstrument(WOPLInstrument *ins, uint8_t *cursor, uint16_t version, uint8_t has_sounding_delays) +{ + int l; + strncpy((char*)cursor, ins->inst_name, 32); + fromSint16BE(ins->note_offset1, cursor + 32); + fromSint16BE(ins->note_offset2, cursor + 34); + cursor[36] = (uint8_t)ins->midi_velocity_offset; + cursor[37] = (uint8_t)ins->second_voice_detune; + cursor[38] = ins->percussion_key_number; + cursor[39] = ins->inst_flags; + cursor[40] = ins->fb_conn1_C0; + cursor[41] = ins->fb_conn2_C0; + for(l = 0; l < 4; l++) + { + size_t off = 42 + (size_t)(l) * 5; + cursor[off + 0] = ins->operators[l].avekf_20; + cursor[off + 1] = ins->operators[l].ksl_l_40; + cursor[off + 2] = ins->operators[l].atdec_60; + cursor[off + 3] = ins->operators[l].susrel_80; + cursor[off + 4] = ins->operators[l].waveform_E0; + } + if((version >= 3) && has_sounding_delays) + { + fromUint16BE(ins->delay_on_ms, cursor + 62); + fromUint16BE(ins->delay_off_ms, cursor + 64); + } +} + +WOPLFile *WOPL_LoadBankFromMem(void *mem, size_t length, int *error) +{ + WOPLFile *outFile = NULL; + uint16_t i = 0, j = 0, k = 0; + uint16_t version = 0; + uint16_t count_melodic_banks = 1; + uint16_t count_percusive_banks = 1; + uint8_t *cursor = (uint8_t *)mem; + + WOPLBank *bankslots[2]; + uint16_t bankslots_sizes[2]; + +#define SET_ERROR(err) \ +{\ + WOPL_Free(outFile);\ + if(error)\ + {\ + *error = err;\ + }\ +} + +#define GO_FORWARD(bytes) { cursor += bytes; length -= bytes; } + + if(!cursor) + { + SET_ERROR(WOPL_ERR_NULL_POINTER); + return NULL; + } + + {/* Magic number */ + if(length < 11) + { + SET_ERROR(WOPL_ERR_UNEXPECTED_ENDING); + return NULL; + } + if(memcmp(cursor, wopl3_magic, 11) != 0) + { + SET_ERROR(WOPL_ERR_BAD_MAGIC); + return NULL; + } + GO_FORWARD(11); + } + + {/* Version code */ + if(length < 2) + { + SET_ERROR(WOPL_ERR_UNEXPECTED_ENDING); + return NULL; + } + version = toUint16LE(cursor); + if(version > wopl_latest_version) + { + SET_ERROR(WOPL_ERR_NEWER_VERSION); + return NULL; + } + GO_FORWARD(2); + } + + {/* Header of WOPL */ + uint8_t head[6]; + if(length < 6) + { + SET_ERROR(WOPL_ERR_UNEXPECTED_ENDING); + return NULL; + } + memcpy(head, cursor, 6); + count_melodic_banks = toUint16BE(head); + count_percusive_banks = toUint16BE(head + 2); + GO_FORWARD(6); + + outFile = WOPL_Init(count_melodic_banks, count_percusive_banks); + if(!outFile) + { + SET_ERROR(WOPL_ERR_OUT_OF_MEMORY); + return NULL; + } + + outFile->version = version; + outFile->opl_flags = head[4]; + outFile->volume_model = head[5]; + } + + bankslots_sizes[0] = count_melodic_banks; + bankslots[0] = outFile->banks_melodic; + bankslots_sizes[1] = count_percusive_banks; + bankslots[1] = outFile->banks_percussive; + + if(version >= 2) /* Bank names and LSB/MSB titles */ + { + for(i = 0; i < 2; i++) + { + for(j = 0; j < bankslots_sizes[i]; j++) + { + if(length < 34) + { + SET_ERROR(WOPL_ERR_UNEXPECTED_ENDING); + return NULL; + } + strncpy(bankslots[i][j].bank_name, (const char*)cursor, 32); + bankslots[i][j].bank_name[32] = '\0'; + bankslots[i][j].bank_midi_lsb = cursor[32]; + bankslots[i][j].bank_midi_msb = cursor[33]; + GO_FORWARD(34); + } + } + } + + {/* Read instruments data */ + uint16_t insSize = 0; + if(version > 2) + insSize = WOPL_INST_SIZE_V3; + else + insSize = WOPL_INST_SIZE_V2; + for(i = 0; i < 2; i++) + { + if(length < (insSize * 128) * (size_t)bankslots_sizes[i]) + { + SET_ERROR(WOPL_ERR_UNEXPECTED_ENDING); + return NULL; + } + + for(j = 0; j < bankslots_sizes[i]; j++) + { + for(k = 0; k < 128; k++) + { + WOPLInstrument *ins = &bankslots[i][j].ins[k]; + WOPL_parseInstrument(ins, cursor, version, 1); + GO_FORWARD(insSize); + } + } + } + } + +#undef GO_FORWARD +#undef SET_ERROR + + return outFile; +} + +int WOPL_LoadInstFromMem(WOPIFile *file, void *mem, size_t length) +{ + uint16_t version = 0; + uint8_t *cursor = (uint8_t *)mem; + uint16_t ins_size; + + if(!cursor) + return WOPL_ERR_NULL_POINTER; + +#define GO_FORWARD(bytes) { cursor += bytes; length -= bytes; } + + {/* Magic number */ + if(length < 11) + return WOPL_ERR_UNEXPECTED_ENDING; + if(memcmp(cursor, wopli_magic, 11) != 0) + return WOPL_ERR_BAD_MAGIC; + GO_FORWARD(11); + } + + {/* Version code */ + if(length < 2) + return WOPL_ERR_UNEXPECTED_ENDING; + version = toUint16LE(cursor); + if(version > wopl_latest_version) + return WOPL_ERR_NEWER_VERSION; + GO_FORWARD(2); + } + + {/* is drum flag */ + if(length < 1) + return WOPL_ERR_UNEXPECTED_ENDING; + file->is_drum = *cursor; + GO_FORWARD(1); + } + + if(version > 2) + /* Skip sounding delays are not part of single-instrument file + * two sizes of uint16_t will be subtracted */ + ins_size = WOPL_INST_SIZE_V3 - (sizeof(uint16_t) * 2); + else + ins_size = WOPL_INST_SIZE_V2; + + if(length < ins_size) + return WOPL_ERR_UNEXPECTED_ENDING; + + WOPL_parseInstrument(&file->inst, cursor, version, 0); + GO_FORWARD(ins_size); + + return WOPL_ERR_OK; +#undef GO_FORWARD +} + +size_t WOPL_CalculateBankFileSize(WOPLFile *file, uint16_t version) +{ + size_t final_size = 0; + size_t ins_size = 0; + + if(version == 0) + version = wopl_latest_version; + + if(!file) + return 0; + final_size += 11 + 2 + 2 + 2 + 1 + 1; + /* + * Magic number, + * Version, + * Count of melodic banks, + * Count of percussive banks, + * Chip specific flags + * Volume Model + */ + + if(version >= 2) + { + /* Melodic banks meta-data */ + final_size += (32 + 1 + 1) * file->banks_count_melodic; + /* Percussive banks meta-data */ + final_size += (32 + 1 + 1) * file->banks_count_percussion; + } + + if(version >= 3) + ins_size = WOPL_INST_SIZE_V3; + else + ins_size = WOPL_INST_SIZE_V2; + /* Melodic instruments */ + final_size += (ins_size * 128) * file->banks_count_melodic; + /* Percusive instruments */ + final_size += (ins_size * 128) * file->banks_count_percussion; + + return final_size; +} + +size_t WOPL_CalculateInstFileSize(WOPIFile *file, uint16_t version) +{ + size_t final_size = 0; + size_t ins_size = 0; + + if(version == 0) + version = wopl_latest_version; + + if(!file) + return 0; + final_size += 11 + 2 + 1; + /* + * Magic number, + * version, + * is percussive instrument + */ + + if(version >= 3) + ins_size = WOPL_INST_SIZE_V3; + else + ins_size = WOPL_INST_SIZE_V2; + final_size += ins_size * 128; + + return final_size; +} + +int WOPL_SaveBankToMem(WOPLFile *file, void *dest_mem, size_t length, uint16_t version, uint16_t force_gm) +{ + uint8_t *cursor = (uint8_t *)dest_mem; + uint16_t ins_size = 0; + uint16_t i, j, k; + uint16_t banks_melodic = force_gm ? 1 : file->banks_count_melodic; + uint16_t banks_percusive = force_gm ? 1 : file->banks_count_percussion; + + WOPLBank *bankslots[2]; + uint16_t bankslots_sizes[2]; + + if(version == 0) + version = wopl_latest_version; + +#define GO_FORWARD(bytes) { cursor += bytes; length -= bytes; } + + if(length < 11) + return WOPL_ERR_UNEXPECTED_ENDING; + memcpy(cursor, wopl3_magic, 11); + GO_FORWARD(11); + + if(length < 2) + return WOPL_ERR_UNEXPECTED_ENDING; + fromUint16LE(version, cursor); + GO_FORWARD(2); + + if(length < 2) + return WOPL_ERR_UNEXPECTED_ENDING; + fromUint16BE(banks_melodic, cursor); + GO_FORWARD(2); + + if(length < 2) + return WOPL_ERR_UNEXPECTED_ENDING; + fromUint16BE(banks_percusive, cursor); + GO_FORWARD(2); + + if(length < 2) + return WOPL_ERR_UNEXPECTED_ENDING; + cursor[0] = file->opl_flags; + cursor[1] = file->volume_model; + GO_FORWARD(2); + + bankslots[0] = file->banks_melodic; + bankslots_sizes[0] = banks_melodic; + bankslots[1] = file->banks_percussive; + bankslots_sizes[1] = banks_percusive; + + if(version >= 2) + { + for(i = 0; i < 2; i++) + { + for(j = 0; j < bankslots_sizes[i]; j++) + { + if(length < 34) + return WOPL_ERR_UNEXPECTED_ENDING; + strncpy((char*)cursor, bankslots[i][j].bank_name, 32); + cursor[32] = bankslots[i][j].bank_midi_lsb; + cursor[33] = bankslots[i][j].bank_midi_msb; + GO_FORWARD(34); + } + } + } + + {/* Write instruments data */ + if(version >= 3) + ins_size = WOPL_INST_SIZE_V3; + else + ins_size = WOPL_INST_SIZE_V2; + for(i = 0; i < 2; i++) + { + if(length < (ins_size * 128) * (size_t)bankslots_sizes[i]) + return WOPL_ERR_UNEXPECTED_ENDING; + + for(j = 0; j < bankslots_sizes[i]; j++) + { + for(k = 0; k < 128; k++) + { + WOPLInstrument *ins = &bankslots[i][j].ins[k]; + WOPL_writeInstrument(ins, cursor, version, 1); + GO_FORWARD(ins_size); + } + } + } + } + + return WOPL_ERR_OK; +#undef GO_FORWARD +} + +int WOPL_SaveInstToMem(WOPIFile *file, void *dest_mem, size_t length, uint16_t version) +{ + uint8_t *cursor = (uint8_t *)dest_mem; + uint16_t ins_size; + + if(!cursor) + return WOPL_ERR_NULL_POINTER; + + if(version == 0) + version = wopl_latest_version; + +#define GO_FORWARD(bytes) { cursor += bytes; length -= bytes; } + + {/* Magic number */ + if(length < 11) + return WOPL_ERR_UNEXPECTED_ENDING; + memcpy(cursor, wopli_magic, 11); + GO_FORWARD(11); + } + + {/* Version code */ + if(length < 2) + return WOPL_ERR_UNEXPECTED_ENDING; + fromUint16LE(version, cursor); + GO_FORWARD(2); + } + + {/* is drum flag */ + if(length < 1) + return WOPL_ERR_UNEXPECTED_ENDING; + *cursor = file->is_drum; + GO_FORWARD(1); + } + + if(version > 2) + /* Skip sounding delays are not part of single-instrument file + * two sizes of uint16_t will be subtracted */ + ins_size = WOPL_INST_SIZE_V3 - (sizeof(uint16_t) * 2); + else + ins_size = WOPL_INST_SIZE_V2; + + if(length < ins_size) + return WOPL_ERR_UNEXPECTED_ENDING; + + WOPL_writeInstrument(&file->inst, cursor, version, 0); + GO_FORWARD(ins_size); + + return WOPL_ERR_OK; +#undef GO_FORWARD +} diff --git a/src/sound/adlmidi/wopl/wopl_file.h b/src/sound/adlmidi/wopl/wopl_file.h new file mode 100644 index 000000000..0e3884243 --- /dev/null +++ b/src/sound/adlmidi/wopl/wopl_file.h @@ -0,0 +1,290 @@ +/* + * Wohlstand's OPL3 Bank File - a bank format to store OPL3 timbre data and setup + * + * Copyright (c) 2015-2018 Vitaly Novichkov + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef WOPL_FILE_H +#define WOPL_FILE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(__STDC_VERSION__) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ < 199901L)) \ + || defined(__STRICT_ANSI__) || !defined(__cplusplus) +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int int16_t; +typedef unsigned short int uint16_t; +#endif + +/* Global OPL flags */ +typedef enum WOPLFileFlags +{ + /* Enable Deep-Tremolo flag */ + WOPL_FLAG_DEEP_TREMOLO = 0x01, + /* Enable Deep-Vibrato flag */ + WOPL_FLAG_DEEP_VIBRATO = 0x02 +} WOPLFileFlags; + +/* Volume scaling model implemented in the libADLMIDI */ +typedef enum WOPL_VolumeModel +{ + WOPL_VM_Generic = 0, + WOPL_VM_Native, + WOPL_VM_DMX, + WOPL_VM_Apogee, + WOPL_VM_Win9x +} WOPL_VolumeModel; + +typedef enum WOPL_InstrumentFlags +{ + /* Is two-operator single-voice instrument (no flags) */ + WOPL_Ins_2op = 0x00, + /* Is true four-operator instrument */ + WOPL_Ins_4op = 0x01, + /* Is pseudo four-operator (two 2-operator voices) instrument */ + WOPL_Ins_Pseudo4op = 0x02, + /* Is a blank instrument entry */ + WOPL_Ins_IsBlank = 0x04, + + /* RythmMode flags mask */ + WOPL_RythmModeMask = 0x38, + + /* Mask of the flags range */ + WOPL_Ins_ALL_MASK = 0x07 +} WOPL_InstrumentFlags; + +typedef enum WOPL_RythmMode +{ + /* RythmMode: BassDrum */ + WOPL_RM_BassDrum = 0x08, + /* RythmMode: Snare */ + WOPL_RM_Snare = 0x10, + /* RythmMode: TomTom */ + WOPL_RM_TomTom = 0x18, + /* RythmMode: Cymbell */ + WOPL_RM_Cymball = 0x20, + /* RythmMode: HiHat */ + WOPL_RM_HiHat = 0x28 +} WOPL_RythmMode; + +/* Error codes */ +typedef enum WOPL_ErrorCodes +{ + WOPL_ERR_OK = 0, + /* Magic number is not maching */ + WOPL_ERR_BAD_MAGIC, + /* Too short file */ + WOPL_ERR_UNEXPECTED_ENDING, + /* Zero banks count */ + WOPL_ERR_INVALID_BANKS_COUNT, + /* Version of file is newer than supported by current version of library */ + WOPL_ERR_NEWER_VERSION, + /* Out of memory */ + WOPL_ERR_OUT_OF_MEMORY, + /* Given null pointer memory data */ + WOPL_ERR_NULL_POINTER +} WOPL_ErrorCodes; + +/* Operator indeces inside of Instrument Entry */ +#define WOPL_OP_CARRIER1 0 +#define WOPL_OP_MODULATOR1 1 +#define WOPL_OP_CARRIER2 2 +#define WOPL_OP_MODULATOR2 3 + +/* OPL3 Oerators data */ +typedef struct WOPLOperator +{ + /* AM/Vib/Env/Ksr/FMult characteristics */ + uint8_t avekf_20; + /* Key Scale Level / Total level register data */ + uint8_t ksl_l_40; + /* Attack / Decay */ + uint8_t atdec_60; + /* Systain and Release register data */ + uint8_t susrel_80; + /* Wave form */ + uint8_t waveform_E0; +} WOPLOperator; + +/* Instrument entry */ +typedef struct WOPLInstrument +{ + /* Title of the instrument */ + char inst_name[34]; + /* MIDI note key (half-tone) offset for an instrument (or a first voice in pseudo-4-op mode) */ + int16_t note_offset1; + /* MIDI note key (half-tone) offset for a second voice in pseudo-4-op mode */ + int16_t note_offset2; + /* MIDI note velocity offset (taken from Apogee TMB format) */ + int8_t midi_velocity_offset; + /* Second voice detune level (taken from DMX OP2) */ + int8_t second_voice_detune; + /* Percussion MIDI base tone number at which this drum will be played */ + uint8_t percussion_key_number; + /* Enum WOPL_InstrumentFlags */ + uint8_t inst_flags; + /* Feedback&Connection register for first and second operators */ + uint8_t fb_conn1_C0; + /* Feedback&Connection register for third and fourth operators */ + uint8_t fb_conn2_C0; + /* Operators register data */ + WOPLOperator operators[4]; + /* Millisecond delay of sounding while key is on */ + uint16_t delay_on_ms; + /* Millisecond delay of sounding after key off */ + uint16_t delay_off_ms; +} WOPLInstrument; + +/* Bank entry */ +typedef struct WOPLBank +{ + /* Name of bank */ + char bank_name[33]; + /* MIDI Bank LSB code */ + uint8_t bank_midi_lsb; + /* MIDI Bank MSB code */ + uint8_t bank_midi_msb; + /* Instruments data of this bank */ + WOPLInstrument ins[128]; +} WOPLBank; + +/* Instrument data file */ +typedef struct WOPIFile +{ + /* Version of instrument file */ + uint16_t version; + /* Is this a percussion instrument */ + uint8_t is_drum; + /* Instrument data */ + WOPLInstrument inst; +} WOPIFile; + +/* Bank data file */ +typedef struct WOPLFile +{ + /* Version of bank file */ + uint16_t version; + /* Count of melodic banks in this file */ + uint16_t banks_count_melodic; + /* Count of percussion banks in this file */ + uint16_t banks_count_percussion; + /* Enum WOPLFileFlags */ + uint8_t opl_flags; + /* Enum WOPL_VolumeModel */ + uint8_t volume_model; + /* dynamically allocated data Melodic banks array */ + WOPLBank *banks_melodic; + /* dynamically allocated data Percussive banks array */ + WOPLBank *banks_percussive; +} WOPLFile; + + +/** + * @brief Initialize blank WOPL data structure with allocated bank data + * @param melodic_banks Count of melodic banks + * @param percussive_banks Count of percussive banks + * @return pointer to heap-allocated WOPL data structure or NULL when out of memory or incorrectly given banks counts + */ +extern WOPLFile *WOPL_Init(uint16_t melodic_banks, uint16_t percussive_banks); + +/** + * @brief Clean up WOPL data file (all allocated bank arrays will be fried too) + * @param file pointer to heap-allocated WOPL data structure + */ +extern void WOPL_Free(WOPLFile *file); + +/** + * @brief Compare two bank entries + * @param bank1 First bank + * @param bank2 Second bank + * @return 1 if banks are equal or 0 if there are different + */ +extern int WOPL_BanksCmp(const WOPLFile *bank1, const WOPLFile *bank2); + + +/** + * @brief Load WOPL bank file from the memory. + * WOPL data structure will be allocated. (don't forget to clear it with WOPL_Free() after use!) + * @param mem Pointer to memory block contains raw WOPL bank file data + * @param length Length of given memory block + * @param error pointer to integer to return an error code. Pass NULL if you don't want to use error codes. + * @return Heap-allocated WOPL file data structure or NULL if any error has occouped + */ +extern WOPLFile *WOPL_LoadBankFromMem(void *mem, size_t length, int *error); + +/** + * @brief Load WOPI instrument file from the memory. + * You must allocate WOPIFile structure by yourself and give the pointer to it. + * @param file Pointer to destinition WOPIFile structure to fill it with parsed data. + * @param mem Pointer to memory block contains raw WOPI instrument file data + * @param length Length of given memory block + * @return 0 if no errors occouped, or an error code of WOPL_ErrorCodes enumeration + */ +extern int WOPL_LoadInstFromMem(WOPIFile *file, void *mem, size_t length); + +/** + * @brief Calculate the size of the output memory block + * @param file Heap-allocated WOPL file data structure + * @param version Destinition version of the file + * @return Size of the raw WOPL file data + */ +extern size_t WOPL_CalculateBankFileSize(WOPLFile *file, uint16_t version); + +/** + * @brief Calculate the size of the output memory block + * @param file Pointer to WOPI file data structure + * @param version Destinition version of the file + * @return Size of the raw WOPI file data + */ +extern size_t WOPL_CalculateInstFileSize(WOPIFile *file, uint16_t version); + +/** + * @brief Write raw WOPL into given memory block + * @param file Heap-allocated WOPL file data structure + * @param dest_mem Destinition memory block pointer + * @param length Length of destinition memory block + * @param version Wanted WOPL version + * @param force_gm Force GM set in saved bank file + * @return Error code or 0 on success + */ +extern int WOPL_SaveBankToMem(WOPLFile *file, void *dest_mem, size_t length, uint16_t version, uint16_t force_gm); + +/** + * @brief Write raw WOPI into given memory block + * @param file Pointer to WOPI file data structure + * @param dest_mem Destinition memory block pointer + * @param length Length of destinition memory block + * @param version Wanted WOPI version + * @return Error code or 0 on success + */ +extern int WOPL_SaveInstToMem(WOPIFile *file, void *dest_mem, size_t length, uint16_t version); + +#ifdef __cplusplus +} +#endif + +#endif /* WOPL_FILE_H */ diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index 525ade7ce..cccc12241 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -319,7 +319,6 @@ protected: class ADLMIDIDevice : public SoftSynthMIDIDevice { struct ADL_MIDIPlayer *Renderer; - TArray shortbuffer; public: ADLMIDIDevice(const char *args); ~ADLMIDIDevice(); @@ -338,7 +337,6 @@ protected: class OPNMIDIDevice : public SoftSynthMIDIDevice { struct OPN2_MIDIPlayer *Renderer; - TArray shortbuffer; public: OPNMIDIDevice(const char *args); ~OPNMIDIDevice(); diff --git a/src/sound/mididevices/music_adlmidi_mididevice.cpp b/src/sound/mididevices/music_adlmidi_mididevice.cpp index 9025c4745..7cece2ec6 100644 --- a/src/sound/mididevices/music_adlmidi_mididevice.cpp +++ b/src/sound/mididevices/music_adlmidi_mididevice.cpp @@ -56,6 +56,22 @@ CUSTOM_CVAR(Int, adl_chips_count, 6, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) } } +CUSTOM_CVAR(Int, adl_emulator_id, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (currSong != nullptr && currSong->GetDeviceType() == MDEV_ADL) + { + MIDIDeviceChanged(-1, true); + } +} + +CUSTOM_CVAR(Bool, adl_run_at_pcm_rate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (currSong != nullptr && currSong->GetDeviceType() == MDEV_ADL) + { + MIDIDeviceChanged(-1, true); + } +} + CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { if (currSong != nullptr && currSong->GetDeviceType() == MDEV_ADL) @@ -64,6 +80,22 @@ CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) } } +CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (currSong != nullptr && currSong->GetDeviceType() == MDEV_ADL) + { + MIDIDeviceChanged(-1, true); + } +} + +CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (adl_use_custom_bank && currSong != nullptr && currSong->GetDeviceType() == MDEV_ADL) + { + MIDIDeviceChanged(-1, true); + } +} + CUSTOM_CVAR(Int, adl_volume_model, ADLMIDI_VolumeModel_DMX, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { if (currSong != nullptr && currSong->GetDeviceType() == MDEV_ADL) @@ -84,7 +116,18 @@ ADLMIDIDevice::ADLMIDIDevice(const char *args) Renderer = adl_init(44100); // todo: make it configurable if (Renderer != nullptr) { - adl_setBank(Renderer, (int)adl_bank); + adl_switchEmulator(Renderer, (int)adl_emulator_id); + adl_setRunAtPcmRate(Renderer, (int)adl_run_at_pcm_rate); +// todo: Implement handling of external or in-resources WOPL bank files and load +/* + if(adl_use_custom_bank) + { + adl_openBankFile(Renderer, (char*)adl_bank_file); + adl_openBankData(Renderer, (char*)adl_bank, (unsigned long)size); + } + else +*/ + adl_setBank(Renderer, (int)adl_bank); adl_setNumChips(Renderer, (int)adl_chips_count); adl_setVolumeRangeModel(Renderer, (int)adl_volume_model); } @@ -176,6 +219,13 @@ void ADLMIDIDevice::HandleLongEvent(const uint8_t *data, int len) { } +static const ADLMIDI_AudioFormat audio_output_format = +{ + ADLMIDI_SampleType_F32, + sizeof(float), + 2 * sizeof(float) +}; + //========================================================================== // // ADLMIDIDevice :: ComputeOutput @@ -184,11 +234,12 @@ void ADLMIDIDevice::HandleLongEvent(const uint8_t *data, int len) void ADLMIDIDevice::ComputeOutput(float *buffer, int len) { - if ((int)shortbuffer.Size() < len*2) shortbuffer.Resize(len*2); - auto result = adl_generate(Renderer, len*2, &shortbuffer[0]); - for(int i=0; i(buffer); + ADL_UInt8* right = reinterpret_cast(buffer + 1); + auto result = adl_generateFormat(Renderer, len * 2, left, right, &audio_output_format); + for(int i=0; i < result; i++) { - buffer[i] = shortbuffer[i] * (3.5f/32768.f); + buffer[i] *= 3.5f; } } diff --git a/src/sound/mididevices/music_opnmidi_mididevice.cpp b/src/sound/mididevices/music_opnmidi_mididevice.cpp index 8c61ab9e7..de27644c3 100644 --- a/src/sound/mididevices/music_opnmidi_mididevice.cpp +++ b/src/sound/mididevices/music_opnmidi_mididevice.cpp @@ -58,6 +58,38 @@ CUSTOM_CVAR(Int, opn_chips_count, 8, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) } } +CUSTOM_CVAR(Int, opn_emulator_id, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN) + { + MIDIDeviceChanged(-1, true); + } +} + +CUSTOM_CVAR(Bool, opn_run_at_pcm_rate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN) + { + MIDIDeviceChanged(-1, true); + } +} + +CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN) + { + MIDIDeviceChanged(-1, true); + } +} + +CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (opn_use_custom_bank && currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN) + { + MIDIDeviceChanged(-1, true); + } +} + //========================================================================== // // OPNMIDIDevice Constructor @@ -70,6 +102,17 @@ OPNMIDIDevice::OPNMIDIDevice(const char *args) Renderer = opn2_init(44100); // todo: make it configurable if (Renderer != nullptr) { + opn2_switchEmulator(Renderer, (int)opn_emulator_id); + opn2_setRunAtPcmRate(Renderer, (int)opn_run_at_pcm_rate); +// todo: Implement handling of external or in-resources WOPN bank files and load +/* + if(opn_use_custom_bank) + { + opn2_openBankFile(Renderer, (char*)opn_bank_file); + opn2_openBankData(Renderer, (char*)opn_bank, (long)size); + } + else + */ int lump = Wads.CheckNumForFullName("xg.wopn"); if (lump < 0) { @@ -167,6 +210,13 @@ void OPNMIDIDevice::HandleLongEvent(const uint8_t *data, int len) { } +static const OPNMIDI_AudioFormat audio_output_format = +{ + OPNMIDI_SampleType_F32, + sizeof(float), + 2 * sizeof(float) +}; + //========================================================================== // // OPNMIDIDevice :: ComputeOutput @@ -175,11 +225,7 @@ void OPNMIDIDevice::HandleLongEvent(const uint8_t *data, int len) void OPNMIDIDevice::ComputeOutput(float *buffer, int len) { - if ((int)shortbuffer.Size() < len*2) shortbuffer.Resize(len*2); - auto result = opn2_generate(Renderer, len*2, &shortbuffer[0]); - for(int i=0; i(buffer); + OPN2_UInt8* right = reinterpret_cast(buffer + 1); + opn2_generateFormat(Renderer, len * 2, left, right, &audio_output_format); } - diff --git a/src/sound/opnmidi/Ym2612_ChipEmu.cpp b/src/sound/opnmidi/chips/gens/Ym2612_Emu.cpp similarity index 95% rename from src/sound/opnmidi/Ym2612_ChipEmu.cpp rename to src/sound/opnmidi/chips/gens/Ym2612_Emu.cpp index 66219ebdc..18285bf84 100644 --- a/src/sound/opnmidi/Ym2612_ChipEmu.cpp +++ b/src/sound/opnmidi/chips/gens/Ym2612_Emu.cpp @@ -2,7 +2,7 @@ // Based on Gens 2.10 ym2612.c -#include "Ym2612_ChipEmu.h" +#include "Ym2612_Emu.h" #include #include @@ -110,7 +110,7 @@ struct state_t int TimerBcnt; // timerB counter = valeur courante du Timer B int Mode; // Mode actuel des voie 3 et 6 (normal / special) int DAC; // DAC enabled flag - channel_t CHANNEL[OPNMIDI_Ym2612_Emu::channel_count]; // Les 6 voies du YM2612 + channel_t CHANNEL[Ym2612_Emu::channel_count]; // Les 6 voies du YM2612 int REG[2][0x100]; // Sauvegardes des valeurs de tout les registres, c'est facultatif // cela nous rend le debuggage plus facile }; @@ -255,9 +255,9 @@ static const unsigned char LFO_FMS_TAB [8] = inline void YM2612_Special_Update() { } -struct OPNMIDI_Ym2612_Impl +struct Ym2612_Impl { - enum { channel_count = OPNMIDI_Ym2612_Emu::channel_count }; + enum { channel_count = Ym2612_Emu::channel_count }; state_t YM2612; int mute_mask; @@ -274,10 +274,10 @@ struct OPNMIDI_Ym2612_Impl void write0( int addr, int data ); void write1( int addr, int data ); void run_timer( int ); - void run( int pair_count, OPNMIDI_Ym2612_Emu::sample_t* ); + void run( int pair_count, Ym2612_Emu::sample_t* ); }; -void OPNMIDI_Ym2612_Impl::KEY_ON( channel_t& ch, int nsl) +void Ym2612_Impl::KEY_ON( channel_t& ch, int nsl) { slot_t *SL = &(ch.SLOT [nsl]); // on recupere le bon pointeur de slot @@ -300,7 +300,7 @@ void OPNMIDI_Ym2612_Impl::KEY_ON( channel_t& ch, int nsl) } -void OPNMIDI_Ym2612_Impl::KEY_OFF(channel_t& ch, int nsl) +void Ym2612_Impl::KEY_OFF(channel_t& ch, int nsl) { slot_t *SL = &(ch.SLOT [nsl]); // on recupere le bon pointeur de slot @@ -318,7 +318,7 @@ void OPNMIDI_Ym2612_Impl::KEY_OFF(channel_t& ch, int nsl) } -int OPNMIDI_Ym2612_Impl::SLOT_SET( int Adr, int data ) +int Ym2612_Impl::SLOT_SET( int Adr, int data ) { int nch = Adr & 3; if ( nch == 3 ) @@ -420,7 +420,7 @@ int OPNMIDI_Ym2612_Impl::SLOT_SET( int Adr, int data ) } -int OPNMIDI_Ym2612_Impl::CHANNEL_SET( int Adr, int data ) +int Ym2612_Impl::CHANNEL_SET( int Adr, int data ) { int num = Adr & 3; if ( num == 3 ) @@ -522,7 +522,7 @@ int OPNMIDI_Ym2612_Impl::CHANNEL_SET( int Adr, int data ) } -int OPNMIDI_Ym2612_Impl::YM_SET(int Adr, int data) +int Ym2612_Impl::YM_SET(int Adr, int data) { switch ( Adr ) { @@ -628,7 +628,7 @@ int OPNMIDI_Ym2612_Impl::YM_SET(int Adr, int data) return 0; } -void OPNMIDI_Ym2612_Impl::set_rate( double sample_rate, double clock_rate ) +void Ym2612_Impl::set_rate( double sample_rate, double clock_rate ) { assert( sample_rate ); assert( clock_rate > sample_rate ); @@ -824,11 +824,11 @@ void OPNMIDI_Ym2612_Impl::set_rate( double sample_rate, double clock_rate ) reset(); } -const char* OPNMIDI_Ym2612_Emu::set_rate( double sample_rate, double clock_rate ) +const char* Ym2612_Emu::set_rate( double sample_rate, double clock_rate ) { if ( !impl ) { - impl = (OPNMIDI_Ym2612_Impl*) malloc( sizeof *impl ); + impl = (Ym2612_Impl*) malloc( sizeof *impl ); if ( !impl ) return "Out of memory"; impl->mute_mask = 0; @@ -840,12 +840,12 @@ const char* OPNMIDI_Ym2612_Emu::set_rate( double sample_rate, double clock_rate return 0; } -OPNMIDI_Ym2612_Emu::~OPNMIDI_Ym2612_Emu() +Ym2612_Emu::~Ym2612_Emu() { free( impl ); } -inline void OPNMIDI_Ym2612_Impl::write0( int opn_addr, int data ) +inline void Ym2612_Impl::write0( int opn_addr, int data ) { assert( (unsigned) data <= 0xFF ); @@ -865,7 +865,7 @@ inline void OPNMIDI_Ym2612_Impl::write0( int opn_addr, int data ) } } -inline void OPNMIDI_Ym2612_Impl::write1( int opn_addr, int data ) +inline void Ym2612_Impl::write1( int opn_addr, int data ) { assert( (unsigned) data <= 0xFF ); @@ -880,12 +880,12 @@ inline void OPNMIDI_Ym2612_Impl::write1( int opn_addr, int data ) } } -void OPNMIDI_Ym2612_Emu::reset() +void Ym2612_Emu::reset() { impl->reset(); } -void OPNMIDI_Ym2612_Impl::reset() +void Ym2612_Impl::reset() { g.LFOcnt = 0; YM2612.TimerA = 0; @@ -949,17 +949,17 @@ void OPNMIDI_Ym2612_Impl::reset() write0( 0x2A, 0x80 ); } -void OPNMIDI_Ym2612_Emu::write0( int addr, int data ) +void Ym2612_Emu::write0( int addr, int data ) { impl->write0( addr, data ); } -void OPNMIDI_Ym2612_Emu::write1( int addr, int data ) +void Ym2612_Emu::write1( int addr, int data ) { impl->write1( addr, data ); } -void OPNMIDI_Ym2612_Emu::mute_voices( int mask ) { impl->mute_mask = mask; } +void Ym2612_Emu::mute_voices( int mask ) { impl->mute_mask = mask; } static void update_envelope_( slot_t* sl ) { @@ -1033,14 +1033,14 @@ inline void update_envelope( slot_t& sl ) template struct ym2612_update_chan { - static void func( tables_t&, channel_t&, OPNMIDI_Ym2612_Emu::sample_t*, int ); + static void func( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int ); }; -typedef void (*ym2612_update_chan_t)( tables_t&, channel_t&, OPNMIDI_Ym2612_Emu::sample_t*, int ); +typedef void (*ym2612_update_chan_t)( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int ); template void ym2612_update_chan::func( tables_t& g, channel_t& ch, - OPNMIDI_Ym2612_Emu::sample_t* buf, int length ) + Ym2612_Emu::sample_t* buf, int length ) { int not_end = ch.SLOT [S3].Ecnt - ENV_END; @@ -1201,7 +1201,7 @@ static const ym2612_update_chan_t UPDATE_CHAN [8] = { &ym2612_update_chan<7>::func }; -void OPNMIDI_Ym2612_Impl::run_timer( int length ) +void Ym2612_Impl::run_timer( int length ) { int const step = 6; int remain = length; @@ -1247,7 +1247,7 @@ void OPNMIDI_Ym2612_Impl::run_timer( int length ) while ( remain > 0 ); } -void OPNMIDI_Ym2612_Impl::run( int pair_count, OPNMIDI_Ym2612_Emu::sample_t* out ) +void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t* out ) { if ( pair_count <= 0 ) return; @@ -1316,4 +1316,4 @@ void OPNMIDI_Ym2612_Impl::run( int pair_count, OPNMIDI_Ym2612_Emu::sample_t* out g.LFOcnt += g.LFOinc * pair_count; } -void OPNMIDI_Ym2612_Emu::run( int pair_count, sample_t* out ) { impl->run( pair_count, out ); } +void Ym2612_Emu::run( int pair_count, sample_t* out ) { impl->run( pair_count, out ); } diff --git a/src/sound/opnmidi/Ym2612_ChipEmu.h b/src/sound/opnmidi/chips/gens/Ym2612_Emu.h similarity index 82% rename from src/sound/opnmidi/Ym2612_ChipEmu.h rename to src/sound/opnmidi/chips/gens/Ym2612_Emu.h index 2628954d5..efce1e2d1 100644 --- a/src/sound/opnmidi/Ym2612_ChipEmu.h +++ b/src/sound/opnmidi/chips/gens/Ym2612_Emu.h @@ -4,31 +4,31 @@ #ifndef YM2612_EMU_H #define YM2612_EMU_H -struct OPNMIDI_Ym2612_Impl; +struct Ym2612_Impl; -class OPNMIDI_Ym2612_Emu { - OPNMIDI_Ym2612_Impl* impl; +class Ym2612_Emu { + Ym2612_Impl* impl; public: - OPNMIDI_Ym2612_Emu() { impl = 0; } - ~OPNMIDI_Ym2612_Emu(); - + Ym2612_Emu() { impl = 0; } + ~Ym2612_Emu(); + // Set output sample rate and chip clock rates, in Hz. Returns non-zero // if error. const char* set_rate( double sample_rate, double clock_rate ); - + // Reset to power-up state void reset(); - + // Mute voice n if bit n (1 << n) of mask is set enum { channel_count = 6 }; void mute_voices( int mask ); - + // Write addr to register 0 then data to register 1 void write0( int addr, int data ); - + // Write addr to register 2 then data to register 3 void write1( int addr, int data ); - + // Run and add pair_count samples into current output buffer contents typedef short sample_t; enum { out_chan_count = 2 }; // stereo diff --git a/src/sound/opnmidi/chips/gens_opn2.cpp b/src/sound/opnmidi/chips/gens_opn2.cpp new file mode 100644 index 000000000..3e8977c77 --- /dev/null +++ b/src/sound/opnmidi/chips/gens_opn2.cpp @@ -0,0 +1,52 @@ +#include "gens_opn2.h" +#include + +#include "gens/Ym2612_Emu.h" + +GensOPN2::GensOPN2() + : chip(new Ym2612_Emu()) +{ + setRate(m_rate, m_clock); +} + +GensOPN2::~GensOPN2() +{ + delete chip; +} + +void GensOPN2::setRate(uint32_t rate, uint32_t clock) +{ + OPNChipBaseBufferedT::setRate(rate, clock); + uint32_t chipRate = isRunningAtPcmRate() ? rate : static_cast(nativeRate); + chip->set_rate(chipRate, clock); // implies reset() +} + +void GensOPN2::reset() +{ + OPNChipBaseBufferedT::reset(); + chip->reset(); +} + +void GensOPN2::writeReg(uint32_t port, uint16_t addr, uint8_t data) +{ + switch (port) + { + case 0: + chip->write0(addr, data); + break; + case 1: + chip->write1(addr, data); + break; + } +} + +void GensOPN2::nativeGenerateN(int16_t *output, size_t frames) +{ + std::memset(output, 0, frames * sizeof(int16_t) * 2); + chip->run((int)frames, output); +} + +const char *GensOPN2::emulatorName() +{ + return "GENS 2.10 OPN2"; +} diff --git a/src/sound/opnmidi/chips/gens_opn2.h b/src/sound/opnmidi/chips/gens_opn2.h new file mode 100644 index 000000000..158ffc69b --- /dev/null +++ b/src/sound/opnmidi/chips/gens_opn2.h @@ -0,0 +1,24 @@ +#ifndef GENS_OPN2_H +#define GENS_OPN2_H + +#include "opn_chip_base.h" + +class Ym2612_Emu; +class GensOPN2 final : public OPNChipBaseBufferedT +{ + Ym2612_Emu *chip; +public: + GensOPN2(); + ~GensOPN2() override; + + bool canRunAtPcmRate() const override { return true; } + void setRate(uint32_t rate, uint32_t clock) override; + void reset() override; + void writeReg(uint32_t port, uint16_t addr, uint8_t data) override; + void nativePreGenerate() override {} + void nativePostGenerate() override {} + void nativeGenerateN(int16_t *output, size_t frames) override; + const char *emulatorName() override; +}; + +#endif // GENS_OPN2_H diff --git a/src/sound/opnmidi/chips/mame/mame_ym2612fm.c b/src/sound/opnmidi/chips/mame/mame_ym2612fm.c new file mode 100644 index 000000000..0628a878a --- /dev/null +++ b/src/sound/opnmidi/chips/mame/mame_ym2612fm.c @@ -0,0 +1,2847 @@ +/* +** +** File: fm2612.c -- software implementation of Yamaha YM2612 FM sound generator +** Split from fm.c to keep 2612 fixes from infecting other OPN chips +** +** Copyright Jarek Burczynski (bujar at mame dot net) +** Copyright Tatsuyuki Satoh , MultiArcadeMachineEmulator development +** +** Version 1.5.1 (Genesis Plus GX ym2612.c rev. 368) +** +*/ + +/* +** History: +** +** 2006~2012 Eke-Eke (Genesis Plus GX): +** Huge thanks to Nemesis, lot of those fixes came from his tests on Sega Genesis hardware +** More informations at http://gendev.spritesmind.net/forum/viewtopic.php?t=386 +** +** TODO: +** +** - core documentation +** - BUSY flag support +** +** CHANGELOG: +** +** 26-09-2017 Eke-Eke (Genesis Plus GX): +** - fixed EG counter loopback behavior (verified on YM3438 die) +** - reverted changes to EG rates 2-7 increment values +** +** xx-xx-xxxx +** - fixed LFO implementation: +** .added support for CH3 special mode: fixes various sound effects (birds in Warlock, bug sound in Aladdin...) +** .inverted LFO AM waveform: fixes Spider-Man & Venom : Separation Anxiety (intro), California Games (surfing event) +** .improved LFO timing accuracy: now updated AFTER sample output, like EG/PG updates, and without any precision loss anymore. +** - improved internal timers emulation +** - adjusted lowest EG rates increment values +** - fixed Attack Rate not being updated in some specific cases (Batman & Robin intro) +** - fixed EG behavior when Attack Rate is maximal +** - fixed EG behavior when SL=0 (Mega Turrican tracks 03,09...) or/and Key ON occurs at minimal attenuation +** - implemented EG output immediate changes on register writes +** - fixed YM2612 initial values (after the reset): fixes missing intro in B.O.B +** - implemented Detune overflow (Ariel, Comix Zone, Shaq Fu, Spiderman & many other games using GEMS sound engine) +** - implemented accurate CSM mode emulation +** - implemented accurate SSG-EG emulation (Asterix, Beavis&Butthead, Bubba'n Stix & many other games) +** - implemented accurate address/data ports behavior +** +** 06-23-2007 Zsolt Vasvari: +** - changed the timing not to require the use of floating point calculations +** +** 03-08-2003 Jarek Burczynski: +** - fixed YM2608 initial values (after the reset) +** - fixed flag and irqmask handling (YM2608) +** - fixed BUFRDY flag handling (YM2608) +** +** 14-06-2003 Jarek Burczynski: +** - implemented all of the YM2608 status register flags +** - implemented support for external memory read/write via YM2608 +** - implemented support for deltat memory limit register in YM2608 emulation +** +** 22-05-2003 Jarek Burczynski: +** - fixed LFO PM calculations (copy&paste bugfix) +** +** 08-05-2003 Jarek Burczynski: +** - fixed SSG support +** +** 22-04-2003 Jarek Burczynski: +** - implemented 100% correct LFO generator (verified on real YM2610 and YM2608) +** +** 15-04-2003 Jarek Burczynski: +** - added support for YM2608's register 0x110 - status mask +** +** 01-12-2002 Jarek Burczynski: +** - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608) +** The addressing patch used for early Neo-Geo games can be removed now. +** +** 26-11-2002 Jarek Burczynski, Nicola Salmoria: +** - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to: +** - added emulation of YM2608 drums. +** - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608) +** +** 16-08-2002 Jarek Burczynski: +** - binary exact Envelope Generator (verified on real YM2203); +** identical to YM2151 +** - corrected 'off by one' error in feedback calculations (when feedback is off) +** - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610) +** +** 18-12-2001 Jarek Burczynski: +** - added SSG-EG support (verified on real YM2203) +** +** 12-08-2001 Jarek Burczynski: +** - corrected sin_tab and tl_tab data (verified on real chip) +** - corrected feedback calculations (verified on real chip) +** - corrected phase generator calculations (verified on real chip) +** - corrected envelope generator calculations (verified on real chip) +** - corrected FM volume level (YM2610 and YM2610B). +** - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) : +** this was needed to calculate YM2610 FM channels output correctly. +** (Each FM channel is calculated as in other chips, but the output of the channel +** gets shifted right by one *before* sending to accumulator. That was impossible to do +** with previous implementation). +** +** 23-07-2001 Jarek Burczynski, Nicola Salmoria: +** - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip) +** +** 11-06-2001 Jarek Burczynski: +** - corrected end of sample bug in ADPCMA_calc_cha(). +** Real YM2610 checks for equality between current and end addresses (only 20 LSB bits). +** +** 08-12-98 hiro-shi: +** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA +** move ROM limit check.(CALC_CH? -> 2610Write1/2) +** test program (ADPCMB_TEST) +** move ADPCM A/B end check. +** ADPCMB repeat flag(no check) +** change ADPCM volume rate (8->16) (32->48). +** +** 09-12-98 hiro-shi: +** change ADPCM volume. (8->16, 48->64) +** replace ym2610 ch0/3 (YM-2610B) +** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff. +** add ADPCM_SHIFT_MASK +** change ADPCMA_DECODE_MIN/MAX. +*/ + + + + +/************************************************************************/ +/* comment of hiro-shi(Hiromitsu Shioya) */ +/* YM2610(B) = OPN-B */ +/* YM2610 : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */ +/* YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */ +/************************************************************************/ + +#include +#include /* for memset */ +#include /* for NULL */ +#include +#include "mamedef.h" +#include "mame_ym2612fm.h" + +static stream_sample_t *DUMMYBUF = NULL; + +/* shared function building option */ +#define BUILD_OPN (BUILD_YM2203||BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B||BUILD_YM2612||BUILD_YM3438) +#define BUILD_OPN_PRESCALER (BUILD_YM2203||BUILD_YM2608) + +#define RSM_ENABLE 0 +#define RSM_FRAC 10 + +/* globals */ +#define TYPE_SSG 0x01 /* SSG support */ +#define TYPE_LFOPAN 0x02 /* OPN type LFO and PAN */ +#define TYPE_6CH 0x04 /* FM 6CH / 3CH */ +#define TYPE_DAC 0x08 /* YM2612's DAC device */ +#define TYPE_ADPCM 0x10 /* two ADPCM units */ +#define TYPE_2610 0x20 /* bogus flag to differentiate 2608 from 2610 */ + + +#define TYPE_YM2203 (TYPE_SSG) +#define TYPE_YM2608 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM) +#define TYPE_YM2610 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM |TYPE_2610) +#define TYPE_YM2612 (TYPE_DAC |TYPE_LFOPAN |TYPE_6CH) + + +/* globals */ +#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ +#define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */ +#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */ +#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */ + +#define FREQ_MASK ((1<>3) + +/* sin waveform table in 'decibel' scale */ +static unsigned int sin_tab[SIN_LEN]; + +/* sustain level table (3dB per step) */ +/* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */ +/* 1, 2, 4, 8, 16, 32, 64 (value)*/ +/* 0.75, 1.5, 3, 6, 12, 24, 48 (dB)*/ + +/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ +/* attenuation value (10 bits) = (SL << 2) << 3 */ +#define SC(db) (UINT32) ( db * (4.0/ENV_STEP) ) +static const UINT32 sl_table[16]={ + SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7), + SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31) +}; +#undef SC + + +#define RATE_STEPS (8) +static const UINT8 eg_inc[19*RATE_STEPS]={ + +/*cycle:0 1 2 3 4 5 6 7*/ + +/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */ +/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */ +/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */ +/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */ + +/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */ +/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */ +/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */ +/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */ + +/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */ +/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */ +/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */ +/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */ + +/*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */ +/*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */ +/*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */ +/*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */ + +/*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */ +/*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */ +/*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */ +}; + + +#define O(a) (a*RATE_STEPS) + +/*note that there is no O(17) in this table - it's directly in the code */ +static const UINT8 eg_rate_select2612[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */ +/* 32 infinite time rates (same as Rate 0) */ +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), + +/* rates 00-11 */ +/* +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +*/ +O(18),O(18),O( 2),O( 3), /* from Nemesis's tests on real YM2612 hardware */ +O( 0),O( 1),O( 2),O( 2), /* Nemesis's tests */ + +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), + +/* rate 12 */ +O( 4),O( 5),O( 6),O( 7), + +/* rate 13 */ +O( 8),O( 9),O(10),O(11), + +/* rate 14 */ +O(12),O(13),O(14),O(15), + +/* rate 15 */ +O(16),O(16),O(16),O(16), + +/* 32 dummy rates (same as 15 3) */ +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16) + +}; +#undef O + +/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/ +/*shift 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0 */ +/*mask 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0 */ + +#define O(a) (a*1) +static const UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */ +/* 32 infinite time rates */ +/* O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), */ + +/* fixed (should be the same as rate 0, even if it makes no difference since increment value is 0 for these rates) */ +O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11), +O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11), +O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11), +O(11),O(11),O(11),O(11),O(11),O(11),O(11),O(11), + +/* rates 00-11 */ +O(11),O(11),O(11),O(11), +O(10),O(10),O(10),O(10), +O( 9),O( 9),O( 9),O( 9), +O( 8),O( 8),O( 8),O( 8), +O( 7),O( 7),O( 7),O( 7), +O( 6),O( 6),O( 6),O( 6), +O( 5),O( 5),O( 5),O( 5), +O( 4),O( 4),O( 4),O( 4), +O( 3),O( 3),O( 3),O( 3), +O( 2),O( 2),O( 2),O( 2), +O( 1),O( 1),O( 1),O( 1), +O( 0),O( 0),O( 0),O( 0), + +/* rate 12 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 13 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 14 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 15 */ +O( 0),O( 0),O( 0),O( 0), + +/* 32 dummy rates (same as 15 3) */ +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0) + +}; +#undef O + +static const UINT8 dt_tab[4 * 32]={ +/* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/ +/* FD=0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* FD=1 */ + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8, +/* FD=2 */ + 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, + 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16, +/* FD=3 */ + 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, + 8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22 +}; + + +/* OPN key frequency number -> key code follow table */ +/* fnum higher 4bit -> keycode lower 2bit */ +static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3}; + + +/* 8 LFO speed parameters */ +/* each value represents number of samples that one LFO level will last for */ +static const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5}; + + + +/*There are 4 different LFO AM depths available, they are: + 0 dB, 1.4 dB, 5.9 dB, 11.8 dB + Here is how it is generated (in EG steps): + + 11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0 + 5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0 + 1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0 + + (1.4 dB is losing precision as you can see) + + It's implemented as generator from 0..126 with step 2 then a shift + right N times, where N is: + 8 for 0 dB + 3 for 1.4 dB + 1 for 5.9 dB + 0 for 11.8 dB +*/ +static const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0}; + + + +/*There are 8 different LFO PM depths available, they are: + 0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents) + + Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10 + (bits 8,9,10 = FNUM MSB from OCT/FNUM register) + + Here we store only first quarter (positive one) of full waveform. + Full table (lfo_pm_table) containing all 128 waveforms is build + at run (init) time. + + One value in table below represents 4 (four) basic LFO steps + (1 PM step = 4 AM steps). + + For example: + at LFO SPEED=0 (which is 108 samples per basic LFO step) + one value from "lfo_pm_output" table lasts for 432 consecutive + samples (4*108=432) and one full LFO waveform cycle lasts for 13824 + samples (32*432=13824; 32 because we store only a quarter of whole + waveform in the table below) +*/ +static 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 */ +/* FNUM BIT 4: 000 0001xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 6 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 7 */ {0, 0, 0, 0, 1, 1, 1, 1}, + +/* FNUM BIT 5: 000 0010xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 6 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 7 */ {0, 0, 1, 1, 2, 2, 2, 3}, + +/* FNUM BIT 6: 000 0100xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 1}, +/* DEPTH 5 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 6 */ {0, 0, 1, 1, 2, 2, 2, 3}, +/* DEPTH 7 */ {0, 0, 2, 3, 4, 4, 5, 6}, + +/* FNUM BIT 7: 000 1000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 1, 1}, +/* DEPTH 3 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 4 */ {0, 0, 0, 1, 1, 1, 1, 2}, +/* DEPTH 5 */ {0, 0, 1, 1, 2, 2, 2, 3}, +/* DEPTH 6 */ {0, 0, 2, 3, 4, 4, 5, 6}, +/* DEPTH 7 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc}, + +/* FNUM BIT 8: 001 0000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 2 */ {0, 0, 0, 1, 1, 1, 2, 2}, +/* DEPTH 3 */ {0, 0, 1, 1, 2, 2, 3, 3}, +/* DEPTH 4 */ {0, 0, 1, 2, 2, 2, 3, 4}, +/* DEPTH 5 */ {0, 0, 2, 3, 4, 4, 5, 6}, +/* DEPTH 6 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc}, +/* DEPTH 7 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, + +/* FNUM BIT 9: 010 0000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 2, 2, 2, 2}, +/* DEPTH 2 */ {0, 0, 0, 2, 2, 2, 4, 4}, +/* DEPTH 3 */ {0, 0, 2, 2, 4, 4, 6, 6}, +/* DEPTH 4 */ {0, 0, 2, 4, 4, 4, 6, 8}, +/* DEPTH 5 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc}, +/* DEPTH 6 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, +/* DEPTH 7 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30}, + +/* FNUM BIT10: 100 0000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 4, 4, 4, 4}, +/* DEPTH 2 */ {0, 0, 0, 4, 4, 4, 8, 8}, +/* DEPTH 3 */ {0, 0, 4, 4, 8, 8, 0xc, 0xc}, +/* DEPTH 4 */ {0, 0, 4, 8, 8, 8, 0xc,0x10}, +/* DEPTH 5 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, +/* DEPTH 6 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30}, +/* DEPTH 7 */ {0, 0,0x20,0x30,0x40,0x40,0x50,0x60}, + +}; + +/* all 128 LFO PM waveforms */ +static 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 */ + +/* register number to channel number , slot offset */ +#define OPN_CHAN(N) (N&3) +#define OPN_SLOT(N) ((N>>2)&3) + +/* slot number */ +#define SLOT1 0 +#define SLOT2 2 +#define SLOT3 1 +#define SLOT4 3 + +/* bit0 = Right enable , bit1 = Left enable */ +#define OUTD_RIGHT 1 +#define OUTD_LEFT 2 +#define OUTD_CENTER 3 + + +/* save output as raw 16-bit sample */ +/* #define SAVE_SAMPLE */ + +#ifdef SAVE_SAMPLE +static FILE *sample[1]; + #if 1 /*save to MONO file */ + #define SAVE_ALL_CHANNELS \ + { signed int pom = lt; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + } + #else /*save to STEREO file */ + #define SAVE_ALL_CHANNELS \ + { signed int pom = lt; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + pom = rt; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + } + #endif +#endif + + +/* struct describing a single operator (SLOT) */ +typedef struct +{ + INT32 *DT; /* detune :dt_tab[DT] */ + UINT8 KSR; /* key scale rate :3-KSR */ + UINT32 ar; /* attack rate */ + UINT32 d1r; /* decay rate */ + UINT32 d2r; /* sustain rate */ + UINT32 rr; /* release rate */ + UINT8 ksr; /* key scale rate :kcode>>(3-KSR) */ + UINT32 mul; /* multiple :ML_TABLE[ML] */ + + /* Phase Generator */ + UINT32 phase; /* phase counter */ + INT32 Incr; /* phase step */ + + /* Envelope Generator */ + UINT8 state; /* phase type */ + UINT32 tl; /* total level: TL << 3 */ + INT32 volume; /* envelope counter */ + UINT32 sl; /* sustain level:sl_table[SL] */ + UINT32 vol_out; /* current output from EG circuit (without AM from LFO) */ + + UINT8 eg_sh_ar; /* (attack state) */ + UINT8 eg_sel_ar; /* (attack state) */ + UINT8 eg_sh_d1r; /* (decay state) */ + UINT8 eg_sel_d1r; /* (decay state) */ + UINT8 eg_sh_d2r; /* (sustain state) */ + UINT8 eg_sel_d2r; /* (sustain state) */ + UINT8 eg_sh_rr; /* (release state) */ + UINT8 eg_sel_rr; /* (release state) */ + + UINT8 ssg; /* SSG-EG waveform */ + UINT8 ssgn; /* SSG-EG negated output */ + + UINT8 key; /* 0=last key was KEY OFF, 1=KEY ON */ + + /* LFO */ + UINT32 AMmask; /* AM enable flag */ + +} FM_SLOT; + +typedef struct +{ + FM_SLOT SLOT[4]; /* four SLOTs (operators) */ + + UINT8 ALGO; /* algorithm */ + UINT8 FB; /* feedback shift */ + INT32 op1_out[2]; /* op1 output for feedback */ + + INT32 *connect1; /* SLOT1 output pointer */ + INT32 *connect3; /* SLOT3 output pointer */ + INT32 *connect2; /* SLOT2 output pointer */ + INT32 *connect4; /* SLOT4 output pointer */ + + INT32 *mem_connect;/* where to put the delayed sample (MEM) */ + INT32 mem_value; /* delayed sample (MEM) value */ + + INT32 pms; /* channel PMS */ + UINT8 ams; /* channel AMS */ + + UINT32 fc; /* fnum,blk:adjusted to sample rate */ + UINT8 kcode; /* key code: */ + UINT32 block_fnum; /* current blk/fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */ + UINT8 Muted; +} FM_CH; + + +typedef struct +{ + /* running_device *device; */ + void * param; /* this chip parameter */ + double freqbase; /* frequency base */ + int timer_prescaler; /* timer prescaler */ + UINT8 irq; /* interrupt level */ + UINT8 irqmask; /* irq mask */ +#if FM_BUSY_FLAG_SUPPORT + TIME_TYPE busy_expiry_time; /* expiry time of the busy status */ +#endif + UINT32 clock; /* master clock (Hz) */ + UINT32 rate; /* internal sampling rate (Hz) */ +#if RSM_ENABLE + INT32 rateratio; /* resampling ratio */ + INT32 framecnt; /* resampling frames count*/ + FMSAMPLE cur_sample[2]; /* previous sample */ + FMSAMPLE prev_sample[2]; /* previous sample */ +#endif + UINT8 address; /* address register */ + UINT8 status; /* status flag */ + UINT32 mode; /* mode CSM / 3SLOT */ + UINT8 fn_h; /* freq latch */ + UINT8 prescaler_sel; /* prescaler selector */ + INT32 TA; /* timer a */ + INT32 TAC; /* timer a counter */ + UINT8 TB; /* timer b */ + INT32 TBC; /* timer b counter */ + /* local time tables */ + INT32 dt_tab[8][32]; /* DeTune table */ + /* Extention Timer and IRQ handler */ + FM_TIMERHANDLER timer_handler; + FM_IRQHANDLER IRQ_Handler; + const ssg_callbacks *SSG; +} FM_ST; + + + +/***********************************************************/ +/* OPN unit */ +/***********************************************************/ + +/* OPN 3slot struct */ +typedef struct +{ + UINT32 fc[3]; /* fnum3,blk3: calculated */ + UINT8 fn_h; /* freq3 latch */ + UINT8 kcode[3]; /* key code */ + UINT32 block_fnum[3]; /* current fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */ + UINT8 key_csm; /* CSM mode Key-ON flag */ +} FM_3SLOT; + +/* OPN/A/B common state */ +typedef struct +{ + UINT8 type; /* chip type */ + FM_ST ST; /* general state */ + FM_3SLOT SL3; /* 3 slot mode state */ + FM_CH *P_CH; /* pointer of CH */ + unsigned int pan[6*2]; /* fm channels output masks (0xffffffff = enable) */ + + UINT32 eg_cnt; /* global envelope generator counter */ + UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/144/3 */ + UINT32 eg_timer_add; /* step of eg_timer */ + UINT32 eg_timer_overflow;/* envelope generator timer overlfows every 3 samples (on real chip) */ + + + /* there are 2048 FNUMs that can be generated using FNUM/BLK registers + but LFO works with one more bit of a precision so we really need 4096 elements */ + UINT32 fn_table[4096]; /* fnumber->increment counter */ + UINT32 fn_max; /* maximal phase increment (used for phase overflow) */ + + /* LFO */ + UINT8 lfo_cnt; /* current LFO phase (out of 128) */ + UINT32 lfo_timer; /* current LFO phase runs at LFO frequency */ + UINT32 lfo_timer_add; /* step of lfo_timer */ + UINT32 lfo_timer_overflow; /* LFO timer overflows every N samples (depends on LFO frequency) */ + UINT32 LFO_AM; /* current LFO AM step */ + UINT32 LFO_PM; /* current LFO PM step */ + + INT32 m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */ + INT32 mem; /* one sample delay memory */ + INT32 out_fm[6]; /* outputs of working channels */ + +} FM_OPN; + +/* here's the virtual YM2612 */ +typedef struct +{ + UINT8 REGS[512]; /* registers */ + FM_OPN OPN; /* OPN state */ + FM_CH CH[6]; /* channel state */ + UINT8 addr_A1; /* address line A1 */ + + /* dac output (YM2612) */ + /* int dacen; */ + UINT8 dacen; + UINT8 dac_test; + INT32 dacout; + UINT8 MuteDAC; + + UINT8 WaveOutMode; + INT32 WaveL; + INT32 WaveR; +} YM2612; + +/* log output level */ +#define LOG_ERR 3 /* ERROR */ +#define LOG_WAR 2 /* WARNING */ +#define LOG_INF 1 /* INFORMATION */ +#define LOG_LEVEL LOG_INF + +#ifndef __RAINE__ +#define LOG(n,x) do { if( (n)>=LOG_LEVEL ) logerror x; } while (0) +#endif + +/* limitter */ +#define Limit(val, max,min) { \ + if ( val > max ) val = max; \ + else if ( val < min ) val = min; \ +} + +#if 0 +#define USE_VGM_INIT_SWITCH +static UINT8 IsVGMInit = 0; +#endif +static UINT8 PseudoSt = 0x00; +/*#include +static FILE* hFile; +static UINT32 FileSample;*/ + +/* status set and IRQ handling */ +INLINE void FM_STATUS_SET(FM_ST *ST,int flag) +{ + /* set status flag */ + ST->status |= flag; + if ( !(ST->irq) && (ST->status & ST->irqmask) ) + { + ST->irq = 1; + /* callback user interrupt handler (IRQ is OFF to ON) */ + if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->param,1); + } +} + +/* status reset and IRQ handling */ +INLINE void FM_STATUS_RESET(FM_ST *ST,int flag) +{ + /* reset status flag */ + ST->status &=~flag; + if ( (ST->irq) && !(ST->status & ST->irqmask) ) + { + ST->irq = 0; + /* callback user interrupt handler (IRQ is ON to OFF) */ + if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->param,0); + } +} + +/* IRQ mask set */ +INLINE void FM_IRQMASK_SET(FM_ST *ST,int flag) +{ + ST->irqmask = flag; + /* IRQ handling check */ + FM_STATUS_SET(ST,0); + FM_STATUS_RESET(ST,0); +} + +INLINE void FM_KEYON(FM_OPN *OPN, FM_CH *CH , int s ) +{ + FM_SLOT *SLOT = &CH->SLOT[s]; + + /* Note by Valley Bell: + I assume that the CSM mode shouldn't affect channels + other than FM3, so I added a check for it here.*/ + if( !SLOT->key && (!OPN->SL3.key_csm || CH == &OPN->P_CH[3])) + { + /* restart Phase Generator */ + SLOT->phase = 0; + + /* reset SSG-EG inversion flag */ + SLOT->ssgn = 0; + + if ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/) + { + SLOT->state = (SLOT->volume <= MIN_ATT_INDEX) ? ((SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC) : EG_ATT; + } + else + { + /* force attenuation level to 0 */ + SLOT->volume = MIN_ATT_INDEX; + + /* directly switch to Decay (or Sustain) */ + SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC; + } + + /* recalculate EG output */ + if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04))) + SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl; + else + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } + + SLOT->key = 1; +} + +INLINE void FM_KEYOFF(FM_OPN *OPN, FM_CH *CH , int s ) +{ + FM_SLOT *SLOT = &CH->SLOT[s]; + + if (SLOT->key && (!OPN->SL3.key_csm || CH == &OPN->P_CH[3])) + { +#ifdef USE_VGM_INIT_SWITCH + if (IsVGMInit) /* workaround for VGMs trimmed with VGMTool */ + { + SLOT->state = EG_OFF; + SLOT->volume = MAX_ATT_INDEX; + SLOT->vol_out= MAX_ATT_INDEX; + } + else +#endif + if (SLOT->state>EG_REL) + { + SLOT->state = EG_REL; /* phase -> Release */ + + /* SSG-EG specific update */ + if (SLOT->ssg&0x08) + { + /* convert EG attenuation level */ + if (SLOT->ssgn ^ (SLOT->ssg&0x04)) + SLOT->volume = (0x200 - SLOT->volume); + + /* force EG attenuation level */ + if (SLOT->volume >= 0x200) + { + SLOT->volume = MAX_ATT_INDEX; + SLOT->state = EG_OFF; + } + + /* recalculate EG output */ + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } + } + } + + SLOT->key = 0; +} + +INLINE void FM_KEYON_CSM(FM_OPN *OPN, FM_CH *CH , int s ) +{ + FM_SLOT *SLOT = &CH->SLOT[s]; + + if( !SLOT->key && !OPN->SL3.key_csm) + { + /* restart Phase Generator */ + SLOT->phase = 0; + + /* reset SSG-EG inversion flag */ + SLOT->ssgn = 0; + + if ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/) + { + SLOT->state = (SLOT->volume <= MIN_ATT_INDEX) ? ((SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC) : EG_ATT; + } + else + { + /* force attenuation level to 0 */ + SLOT->volume = MIN_ATT_INDEX; + + /* directly switch to Decay (or Sustain) */ + SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC; + } + + /* recalculate EG output */ + if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04))) + SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl; + else + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } +} + +INLINE void FM_KEYOFF_CSM(FM_CH *CH , int s ) +{ + FM_SLOT *SLOT = &CH->SLOT[s]; + if (!SLOT->key) + { +#ifdef USE_VGM_INIT_SWITCH + if (IsVGMInit) + { + SLOT->state = EG_OFF; + SLOT->volume = MAX_ATT_INDEX; + SLOT->vol_out= MAX_ATT_INDEX; + } + else +#endif + if (SLOT->state>EG_REL) + { + SLOT->state = EG_REL; /* phase -> Release */ + + /* SSG-EG specific update */ + if (SLOT->ssg&0x08) + { + /* convert EG attenuation level */ + if (SLOT->ssgn ^ (SLOT->ssg&0x04)) + SLOT->volume = (0x200 - SLOT->volume); + + /* force EG attenuation level */ + if (SLOT->volume >= 0x200) + { + SLOT->volume = MAX_ATT_INDEX; + SLOT->state = EG_OFF; + } + + /* recalculate EG output */ + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } + } + } +} + +/* OPN Mode Register Write */ +INLINE void set_timers( FM_OPN *OPN, FM_ST *ST, void *n, int v ) +{ + /* b7 = CSM MODE */ + /* b6 = 3 slot mode */ + /* b5 = reset b */ + /* b4 = reset a */ + /* b3 = timer enable b */ + /* b2 = timer enable a */ + /* b1 = load b */ + /* b0 = load a */ + + if ((OPN->ST.mode ^ v) & 0xC0) + { + /* phase increment need to be recalculated */ + OPN->P_CH[2].SLOT[SLOT1].Incr=-1; + + /* CSM mode disabled and CSM key ON active*/ + if (((v & 0xC0) != 0x80) && OPN->SL3.key_csm) + { + /* CSM Mode Key OFF (verified by Nemesis on real hardware) */ + FM_KEYOFF_CSM(&OPN->P_CH[2],SLOT1); + FM_KEYOFF_CSM(&OPN->P_CH[2],SLOT2); + FM_KEYOFF_CSM(&OPN->P_CH[2],SLOT3); + FM_KEYOFF_CSM(&OPN->P_CH[2],SLOT4); + OPN->SL3.key_csm = 0; + } + } + + /* reset Timer b flag */ + if( v & 0x20 ) + FM_STATUS_RESET(ST,0x02); + /* reset Timer a flag */ + if( v & 0x10 ) + FM_STATUS_RESET(ST,0x01); + /* load b */ + if ((v&2) && !(ST->mode&2)) + { + ST->TBC = ( 256-ST->TB)<<4; + /* External timer handler */ + if (ST->timer_handler) (ST->timer_handler)(n,1,ST->TBC * ST->timer_prescaler,(int)ST->clock); + } + /* load a */ + if ((v&1) && !(ST->mode&1)) + { + ST->TAC = (1024-ST->TA); + /* External timer handler */ + if (ST->timer_handler) (ST->timer_handler)(n,0,ST->TAC * ST->timer_prescaler,(int)ST->clock); + ST->TAC *= 4096; + } + + ST->mode = (UINT32)v; +} + + +/* Timer A Overflow */ +INLINE void TimerAOver(FM_ST *ST) +{ + /* set status (if enabled) */ + if(ST->mode & 0x04) FM_STATUS_SET(ST,0x01); + /* clear or reload the counter */ + ST->TAC = (1024-ST->TA); + if (ST->timer_handler) (ST->timer_handler)(ST->param,0,ST->TAC * ST->timer_prescaler,(int)ST->clock); + ST->TAC *= 4096; +} +/* Timer B Overflow */ +INLINE void TimerBOver(FM_ST *ST) +{ + /* set status (if enabled) */ + if(ST->mode & 0x08) FM_STATUS_SET(ST,0x02); + /* clear or reload the counter */ + ST->TBC = ( 256-ST->TB)<<4; + if (ST->timer_handler) (ST->timer_handler)(ST->param,1,ST->TBC * ST->timer_prescaler,(int)ST->clock); +} + + +#if FM_INTERNAL_TIMER +/* ----- internal timer mode , update timer */ +/* Valley Bell: defines fixed */ + +/* ---------- calculate timer A ---------- */ + #define INTERNAL_TIMER_A(ST,CSM_CH) \ + { \ + if( (ST)->TAC && ((ST)->timer_handler==0) ) \ + if( ((ST)->TAC -= (int)((ST)->freqbase*4096)) <= 0 ) \ + { \ + TimerAOver( ST ); \ + /* CSM mode total level latch and auto key on */ \ + if( (ST)->mode & 0x80 ) \ + CSMKeyControll( OPN, CSM_CH ); \ + } \ + } +/* ---------- calculate timer B ---------- */ + #define INTERNAL_TIMER_B(ST,step) \ + { \ + if( (ST)->TBC && ((ST)->timer_handler==0) ) \ + if( ((ST)->TBC -= (int)((ST)->freqbase*4096*step)) <= 0 ) \ + TimerBOver( ST ); \ + } +#else /* FM_INTERNAL_TIMER */ +/* external timer mode */ +#define INTERNAL_TIMER_A(ST,CSM_CH) +#define INTERNAL_TIMER_B(ST,step) +#endif /* FM_INTERNAL_TIMER */ + + + +#if FM_BUSY_FLAG_SUPPORT +#define FM_BUSY_CLEAR(ST) ((ST)->busy_expiry_time = UNDEFINED_TIME) +INLINE UINT8 FM_STATUS_FLAG(FM_ST *ST) +{ + if( COMPARE_TIMES(ST->busy_expiry_time, UNDEFINED_TIME) != 0 ) + { + if (COMPARE_TIMES(ST->busy_expiry_time, FM_GET_TIME_NOW(ST->device->machine)) > 0) + return ST->status | 0x80; /* with busy */ + /* expire */ + FM_BUSY_CLEAR(ST); + } + return ST->status; +} +INLINE void FM_BUSY_SET(FM_ST *ST,int busyclock ) +{ + TIME_TYPE expiry_period = MULTIPLY_TIME_BY_INT(ATTOTIME_IN_HZ(ST->clock), busyclock * ST->timer_prescaler); + ST->busy_expiry_time = ADD_TIMES(FM_GET_TIME_NOW(ST->device->machine), expiry_period); +} +#else +#define FM_STATUS_FLAG(ST) ((ST)->status) +#define FM_BUSY_SET(ST,bclock) {} +#define FM_BUSY_CLEAR(ST) {} +#endif + + +/* set algorithm connection */ +INLINE void setup_connection( FM_OPN *OPN, FM_CH *CH, int ch ) +{ + INT32 *carrier = &OPN->out_fm[ch]; + + INT32 **om1 = &CH->connect1; + INT32 **om2 = &CH->connect3; + INT32 **oc1 = &CH->connect2; + + INT32 **memc = &CH->mem_connect; + + switch( CH->ALGO ) + { + case 0: + /* M1---C1---MEM---M2---C2---OUT */ + *om1 = &OPN->c1; + *oc1 = &OPN->mem; + *om2 = &OPN->c2; + *memc= &OPN->m2; + break; + case 1: + /* M1------+-MEM---M2---C2---OUT */ + /* C1-+ */ + *om1 = &OPN->mem; + *oc1 = &OPN->mem; + *om2 = &OPN->c2; + *memc= &OPN->m2; + break; + case 2: + /* M1-----------------+-C2---OUT */ + /* C1---MEM---M2-+ */ + *om1 = &OPN->c2; + *oc1 = &OPN->mem; + *om2 = &OPN->c2; + *memc= &OPN->m2; + break; + case 3: + /* M1---C1---MEM------+-C2---OUT */ + /* M2-+ */ + *om1 = &OPN->c1; + *oc1 = &OPN->mem; + *om2 = &OPN->c2; + *memc= &OPN->c2; + break; + case 4: + /* M1---C1-+-OUT */ + /* M2---C2-+ */ + /* MEM: not used */ + *om1 = &OPN->c1; + *oc1 = carrier; + *om2 = &OPN->c2; + *memc= &OPN->mem; /* store it anywhere where it will not be used */ + break; + case 5: + /* +----C1----+ */ + /* M1-+-MEM---M2-+-OUT */ + /* +----C2----+ */ + *om1 = 0; /* special mark */ + *oc1 = carrier; + *om2 = carrier; + *memc= &OPN->m2; + break; + case 6: + /* M1---C1-+ */ + /* M2-+-OUT */ + /* C2-+ */ + /* MEM: not used */ + *om1 = &OPN->c1; + *oc1 = carrier; + *om2 = carrier; + *memc= &OPN->mem; /* store it anywhere where it will not be used */ + break; + case 7: + /* M1-+ */ + /* C1-+-OUT */ + /* M2-+ */ + /* C2-+ */ + /* MEM: not used*/ + *om1 = carrier; + *oc1 = carrier; + *om2 = carrier; + *memc= &OPN->mem; /* store it anywhere where it will not be used */ + break; + } + + CH->connect4 = carrier; +} + +/* set detune & multiple */ +INLINE void set_det_mul(FM_ST *ST,FM_CH *CH,FM_SLOT *SLOT,int v) +{ + SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1; + SLOT->DT = ST->dt_tab[(v>>4)&7]; + CH->SLOT[SLOT1].Incr=-1; +} + +/* set total level */ +INLINE void set_tl(FM_CH *CH,FM_SLOT *SLOT , int v) +{ + SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */ + (void)CH; + + /* recalculate EG output */ + if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04)) && (SLOT->state > EG_REL)) + SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl; + else + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; +} + +/* set attack rate & key scale */ +INLINE void set_ar_ksr(UINT8 type, FM_CH *CH,FM_SLOT *SLOT,int v) +{ + UINT8 old_KSR = SLOT->KSR; + (void)type; + + SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + + SLOT->KSR = 3-(v>>6); + if (SLOT->KSR != old_KSR) + { + CH->SLOT[SLOT1].Incr=-1; + } + + /* Even if it seems unnecessary, in some odd case, KSR and KC are both modified */ + /* and could result in SLOT->kc remaining unchanged. */ + /* In such case, AR values would not be recalculated despite SLOT->ar has changed */ + /* This fixes the introduction music of Batman & Robin (Eke-Eke) */ + if ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/) + { + SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; + SLOT->eg_sel_ar = eg_rate_select2612[SLOT->ar + SLOT->ksr ]; + } + else + { + SLOT->eg_sh_ar = 0; + SLOT->eg_sel_ar = 18*RATE_STEPS; /* verified by Nemesis on real hardware */ + } +} + +/* set decay rate */ +INLINE void set_dr(UINT8 type, FM_SLOT *SLOT,int v) +{ + (void)type; + SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + + SLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr]; + SLOT->eg_sel_d1r= eg_rate_select2612[SLOT->d1r + SLOT->ksr]; +} + +/* set sustain rate */ +INLINE void set_sr(UINT8 type, FM_SLOT *SLOT,int v) +{ + (void)type; + SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + + SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr]; + SLOT->eg_sel_d2r= eg_rate_select2612[SLOT->d2r + SLOT->ksr]; +} + +/* set release rate */ +INLINE void set_sl_rr(UINT8 type, FM_SLOT *SLOT,int v) +{ + (void)type; + SLOT->sl = sl_table[ v>>4 ]; + + /* check EG state changes */ + if ((SLOT->state == EG_DEC) && (SLOT->volume >= (INT32)(SLOT->sl))) + SLOT->state = EG_SUS; + + SLOT->rr = 34 + ((v&0x0f)<<2); + + SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr]; + SLOT->eg_sel_rr = eg_rate_select2612[SLOT->rr + SLOT->ksr]; +} + +/* advance LFO to next sample */ +INLINE void advance_lfo(FM_OPN *OPN) +{ + if (OPN->lfo_timer_overflow) /* LFO enabled ? */ + { + /* increment LFO timer */ + OPN->lfo_timer += OPN->lfo_timer_add; + + /* when LFO is enabled, one level will last for 108, 77, 71, 67, 62, 44, 8 or 5 samples */ + while (OPN->lfo_timer >= OPN->lfo_timer_overflow) + { + OPN->lfo_timer -= OPN->lfo_timer_overflow; + + /* There are 128 LFO steps */ + OPN->lfo_cnt = ( OPN->lfo_cnt + 1 ) & 127; + + /* Valley Bell: Replaced old code (non-inverted triangle) with + the one from Genesis Plus GX 1.71. */ + /* triangle (inverted) */ + /* AM: from 126 to 0 step -2, 0 to 126 step +2 */ + if (OPN->lfo_cnt<64) + OPN->LFO_AM = (UINT32)(OPN->lfo_cnt ^ 63) << 1; + else + OPN->LFO_AM = (UINT32)(OPN->lfo_cnt & 63) << 1; + + /* PM works with 4 times slower clock */ + OPN->LFO_PM = OPN->lfo_cnt >> 2; + } + } +} + +INLINE void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT) +{ + /* unsigned int out; */ + unsigned int i = 4; /* four operators per channel */ + + do + { + switch(SLOT->state) + { + case EG_ATT: /* attack phase */ + if (!(OPN->eg_cnt & ((1<eg_sh_ar)-1))) + { + /* update attenuation level */ + SLOT->volume += (~SLOT->volume * (eg_inc[SLOT->eg_sel_ar + ((OPN->eg_cnt>>SLOT->eg_sh_ar)&7)]))>>4; + + /* check phase transition*/ + if (SLOT->volume <= MIN_ATT_INDEX) + { + SLOT->volume = MIN_ATT_INDEX; + SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC; /* special case where SL=0 */ + } + + /* recalculate EG output */ + if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04))) /* SSG-EG Output Inversion */ + SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl; + else + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } + break; + + case EG_DEC: /* decay phase */ + if (!(OPN->eg_cnt & ((1<eg_sh_d1r)-1))) + { + /* SSG EG type */ + if (SLOT->ssg&0x08) + { + /* update attenuation level */ + if (SLOT->volume < 0x200) + { + SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)]; + + /* recalculate EG output */ + if (SLOT->ssgn ^ (SLOT->ssg&0x04)) /* SSG-EG Output Inversion */ + SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl; + else + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } + + } + else + { + /* update attenuation level */ + SLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)]; + + /* recalculate EG output */ + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } + + /* check phase transition*/ + if (SLOT->volume >= (INT32)(SLOT->sl)) + SLOT->state = EG_SUS; + } + break; + + case EG_SUS: /* sustain phase */ + if (!(OPN->eg_cnt & ((1<eg_sh_d2r)-1))) + { + /* SSG EG type */ + if (SLOT->ssg&0x08) + { + /* update attenuation level */ + if (SLOT->volume < 0x200) + { + SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)]; + + /* recalculate EG output */ + if (SLOT->ssgn ^ (SLOT->ssg&0x04)) /* SSG-EG Output Inversion */ + SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl; + else + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } + } + else + { + /* update attenuation level */ + SLOT->volume += eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)]; + + /* check phase transition*/ + if ( SLOT->volume >= MAX_ATT_INDEX ) + SLOT->volume = MAX_ATT_INDEX; + /* do not change SLOT->state (verified on real chip) */ + + /* recalculate EG output */ + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } + } + break; + + case EG_REL: /* release phase */ + if (!(OPN->eg_cnt & ((1<eg_sh_rr)-1))) + { + /* SSG EG type */ + if (SLOT->ssg&0x08) + { + /* update attenuation level */ + if (SLOT->volume < 0x200) + SLOT->volume += 4 * eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)]; + /* check phase transition */ + if (SLOT->volume >= 0x200) + { + SLOT->volume = MAX_ATT_INDEX; + SLOT->state = EG_OFF; + } + } + else + { + /* update attenuation level */ + SLOT->volume += eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)]; + + /* check phase transition*/ + if (SLOT->volume >= MAX_ATT_INDEX) + { + SLOT->volume = MAX_ATT_INDEX; + SLOT->state = EG_OFF; + } + } + + /* recalculate EG output */ + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + + } + break; + } + + /* Valley Bell: These few lines are missing in Genesis Plus GX' ym2612 core file. + Disabling them fixes the SSG-EG. + Additional Note: Asterix and the Great Rescue: Level 1 sounds "better" with these lines, + but less accurate. */ + #if 0 + out = ((UINT32)SLOT->volume); + + /* negate output (changes come from alternate bit, init comes from attack bit) */ + if ((SLOT->ssg&0x08) && (SLOT->ssgn&2) && (SLOT->state > EG_REL)) + out ^= MAX_ATT_INDEX; + + /* we need to store the result here because we are going to change ssgn + in next instruction */ + SLOT->vol_out = out + SLOT->tl; + #endif + + SLOT++; + i--; + } while (i); + +} + +/* SSG-EG update process */ +/* The behavior is based upon Nemesis tests on real hardware */ +/* This is actually executed before each samples */ +INLINE void update_ssg_eg_channel(FM_SLOT *SLOT) +{ + unsigned int i = 4; /* four operators per channel */ + + do + { + /* detect SSG-EG transition */ + /* this is not required during release phase as the attenuation has been forced to MAX and output invert flag is not used */ + /* if an Attack Phase is programmed, inversion can occur on each sample */ + if ((SLOT->ssg & 0x08) && (SLOT->volume >= 0x200) && (SLOT->state > EG_REL)) + { + if (SLOT->ssg & 0x01) /* bit 0 = hold SSG-EG */ + { + /* set inversion flag */ + if (SLOT->ssg & 0x02) + SLOT->ssgn = 4; + + /* force attenuation level during decay phases */ + if ((SLOT->state != EG_ATT) && !(SLOT->ssgn ^ (SLOT->ssg & 0x04))) + SLOT->volume = MAX_ATT_INDEX; + } + else /* loop SSG-EG */ + { + /* toggle output inversion flag or reset Phase Generator */ + if (SLOT->ssg & 0x02) + SLOT->ssgn ^= 4; + else + SLOT->phase = 0; + + /* same as Key ON */ + if (SLOT->state != EG_ATT) + { + if ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/) + { + SLOT->state = (SLOT->volume <= MIN_ATT_INDEX) ? ((SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC) : EG_ATT; + } + else + { + /* Attack Rate is maximal: directly switch to Decay or Substain */ + SLOT->volume = MIN_ATT_INDEX; + SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC; + } + } + } + + /* recalculate EG output */ + if (SLOT->ssgn ^ (SLOT->ssg&0x04)) + SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl; + else + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } + + /* next slot */ + SLOT++; + i--; + } while (i); +} + + +INLINE void update_phase_lfo_slot(FM_OPN *OPN, FM_SLOT *SLOT, INT32 pms, UINT32 block_fnum) +{ + UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8; + INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + pms + OPN->LFO_PM ]; + + block_fnum = block_fnum*2 + lfo_fn_table_index_offset; + + if (lfo_fn_table_index_offset) /* LFO phase modulation active */ + { + UINT8 blk = (block_fnum&0x7000) >> 12; + UINT32 fn = block_fnum & 0xfff; + + /* recalculate keyscale code */ + /*int kc = (blk<<2) | opn_fktable[fn >> 7];*/ + /* This really stupid bug caused a read outside of the + array [size 0x10] and returned invalid values. + This caused an annoying vibrato for some notes. + (Note: seems to be a copy-and-paste from OPNWriteReg -> case 0xA0) + Why are MAME cores always SOO buggy ?! */ + /* Oh, and before I forget: it's correct in fm.c */ + int kc = (blk<<2) | opn_fktable[fn >> 8]; + /* Thanks to Blargg - his patch that helped me to find this bug */ + + /* recalculate (frequency) phase increment counter */ + int fc = (OPN->fn_table[fn]>>(7-blk)) + SLOT->DT[kc]; + + /* (frequency) phase overflow (credits to Nemesis) */ + if (fc < 0) fc += OPN->fn_max; + + /* update phase */ + SLOT->phase += (fc * SLOT->mul) >> 1; + } + else /* LFO phase modulation = zero */ + { + SLOT->phase += SLOT->Incr; + } +} + +INLINE void update_phase_lfo_channel(FM_OPN *OPN, FM_CH *CH) +{ + UINT32 block_fnum = CH->block_fnum; + + UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8; + INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + OPN->LFO_PM ]; + + block_fnum = block_fnum*2 + lfo_fn_table_index_offset; + + if (lfo_fn_table_index_offset) /* LFO phase modulation active */ + { + UINT8 blk = (block_fnum&0x7000) >> 12; + UINT32 fn = block_fnum & 0xfff; + + /* recalculate keyscale code */ + /*int kc = (blk<<2) | opn_fktable[fn >> 7];*/ + /* the same stupid bug as above */ + int kc = (blk<<2) | opn_fktable[fn >> 8]; + + /* recalculate (frequency) phase increment counter */ + int fc = (OPN->fn_table[fn]>>(7-blk)); + + /* (frequency) phase overflow (credits to Nemesis) */ + int finc = fc + CH->SLOT[SLOT1].DT[kc]; + if (finc < 0) finc += OPN->fn_max; + CH->SLOT[SLOT1].phase += (finc*CH->SLOT[SLOT1].mul) >> 1; + + finc = fc + CH->SLOT[SLOT2].DT[kc]; + if (finc < 0) finc += OPN->fn_max; + CH->SLOT[SLOT2].phase += (finc*CH->SLOT[SLOT2].mul) >> 1; + + finc = fc + CH->SLOT[SLOT3].DT[kc]; + if (finc < 0) finc += OPN->fn_max; + CH->SLOT[SLOT3].phase += (finc*CH->SLOT[SLOT3].mul) >> 1; + + finc = fc + CH->SLOT[SLOT4].DT[kc]; + if (finc < 0) finc += OPN->fn_max; + CH->SLOT[SLOT4].phase += (finc*CH->SLOT[SLOT4].mul) >> 1; + } + else /* LFO phase modulation = zero */ + { + CH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr; + CH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr; + CH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr; + CH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr; + } +} + +/* update phase increment and envelope generator */ +INLINE void refresh_fc_eg_slot(FM_OPN *OPN, FM_SLOT *SLOT , int fc , int kc ) +{ + int ksr = kc >> SLOT->KSR; + + fc += SLOT->DT[kc]; + + /* detects frequency overflow (credits to Nemesis) */ + if (fc < 0) fc += OPN->fn_max; + + /* (frequency) phase increment counter */ + SLOT->Incr = (fc * SLOT->mul) >> 1; + + if( SLOT->ksr != ksr ) + { + SLOT->ksr = ksr; + + /* calculate envelope generator rates */ + if ((SLOT->ar + SLOT->ksr) < 32+62) + { + SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; + SLOT->eg_sel_ar = eg_rate_select2612[SLOT->ar + SLOT->ksr ]; + } + else + { + SLOT->eg_sh_ar = 0; + SLOT->eg_sel_ar = 18*RATE_STEPS; /* verified by Nemesis on real hardware (Attack phase is blocked) */ + } + + SLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr]; + SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr]; + SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr]; + + SLOT->eg_sel_d1r= eg_rate_select2612[SLOT->d1r + SLOT->ksr]; + SLOT->eg_sel_d2r= eg_rate_select2612[SLOT->d2r + SLOT->ksr]; + SLOT->eg_sel_rr = eg_rate_select2612[SLOT->rr + SLOT->ksr]; + } +} + +/* update phase increment counters */ +INLINE void refresh_fc_eg_chan(FM_OPN *OPN, FM_CH *CH ) +{ + if( CH->SLOT[SLOT1].Incr==-1) + { + int fc = CH->fc; + int kc = CH->kcode; + refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT1] , fc , kc ); + refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT2] , fc , kc ); + refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT3] , fc , kc ); + refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT4] , fc , kc ); + } +} + +#define volume_calc(OP) ((OP)->vol_out + (AM & (OP)->AMmask)) + +INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm) +{ + UINT32 p; + + p = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + (pm<<15))) >> FREQ_SH ) & SIN_MASK ]; + + if (p >= TL_TAB_LEN) + return 0; + return tl_tab[p]; +} + +INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm) +{ + UINT32 p = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK ]; + if (p >= TL_TAB_LEN) + return 0; + return tl_tab[p]; +} + +INLINE void chan_calc(YM2612 *F2612, FM_OPN *OPN, FM_CH *CH) +{ + UINT32 AM = OPN->LFO_AM >> CH->ams; + unsigned int eg_out; + + if (CH->Muted) + return; + + OPN->m2 = OPN->c1 = OPN->c2 = OPN->mem = 0; + + *CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */ + + eg_out = volume_calc(&CH->SLOT[SLOT1]); + { + INT32 out = CH->op1_out[0] + CH->op1_out[1]; + CH->op1_out[0] = CH->op1_out[1]; + + if( !CH->connect1 ) + { + /* algorithm 5 */ + OPN->mem = OPN->c1 = OPN->c2 = CH->op1_out[0]; + } + else + { + /* other algorithms */ + *CH->connect1 += CH->op1_out[0]; + } + + + CH->op1_out[1] = 0; + if( eg_out < ENV_QUIET ) /* SLOT 1 */ + { + if (!CH->FB) + out=0; + + CH->op1_out[1] = op_calc1(CH->SLOT[SLOT1].phase, eg_out, (out<FB) ); + } + } + + eg_out = volume_calc(&CH->SLOT[SLOT3]); + if( eg_out < ENV_QUIET ) /* SLOT 3 */ + *CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, OPN->m2); + + eg_out = volume_calc(&CH->SLOT[SLOT2]); + if( eg_out < ENV_QUIET ) /* SLOT 2 */ + *CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, OPN->c1); + + eg_out = volume_calc(&CH->SLOT[SLOT4]); + if( eg_out < ENV_QUIET ) /* SLOT 4 */ + *CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, OPN->c2); + + + /* store current MEM */ + CH->mem_value = OPN->mem; + + /* update phase counters AFTER output calculations */ + if(CH->pms) + { + /* add support for 3 slot mode */ + if ((OPN->ST.mode & 0xC0) && (CH == &F2612->CH[2])) + { + update_phase_lfo_slot(OPN, &CH->SLOT[SLOT1], CH->pms, OPN->SL3.block_fnum[1]); + update_phase_lfo_slot(OPN, &CH->SLOT[SLOT2], CH->pms, OPN->SL3.block_fnum[2]); + update_phase_lfo_slot(OPN, &CH->SLOT[SLOT3], CH->pms, OPN->SL3.block_fnum[0]); + update_phase_lfo_slot(OPN, &CH->SLOT[SLOT4], CH->pms, CH->block_fnum); + } + else update_phase_lfo_channel(OPN, CH); + } + else /* no LFO phase modulation */ + { + CH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr; + CH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr; + CH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr; + CH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr; + } +} + +static void FMCloseTable( void ) +{ +#ifdef SAVE_SAMPLE + fclose(sample[0]); +#endif + return; +} + + +/* CSM Key Controll */ +INLINE void CSMKeyControll(FM_OPN *OPN, FM_CH *CH) +{ + /* all key ON (verified by Nemesis on real hardware) */ + FM_KEYON_CSM(OPN,CH,SLOT1); + FM_KEYON_CSM(OPN,CH,SLOT2); + FM_KEYON_CSM(OPN,CH,SLOT3); + FM_KEYON_CSM(OPN,CH,SLOT4); + OPN->SL3.key_csm = 1; +} + +#ifdef __STATE_H__ +/* FM channel save , internal state only */ +static void FMsave_state_channel(running_device *device,FM_CH *CH,int num_ch) +{ + int slot , ch; + + for(ch=0;chop1_out); + state_save_register_device_item(device, ch, CH->fc); + /* slots */ + for(slot=0;slot<4;slot++) + { + FM_SLOT *SLOT = &CH->SLOT[slot]; + state_save_register_device_item(device, ch * 4 + slot, SLOT->phase); + state_save_register_device_item(device, ch * 4 + slot, SLOT->state); + state_save_register_device_item(device, ch * 4 + slot, SLOT->volume); + } + } +} + +static void FMsave_state_st(running_device *device,FM_ST *ST) +{ +#if FM_BUSY_FLAG_SUPPORT + state_save_register_device_item(device, 0, ST->busy_expiry_time.seconds ); + state_save_register_device_item(device, 0, ST->busy_expiry_time.attoseconds ); +#endif + state_save_register_device_item(device, 0, ST->address ); + state_save_register_device_item(device, 0, ST->irq ); + state_save_register_device_item(device, 0, ST->irqmask ); + state_save_register_device_item(device, 0, ST->status ); + state_save_register_device_item(device, 0, ST->mode ); + state_save_register_device_item(device, 0, ST->prescaler_sel ); + state_save_register_device_item(device, 0, ST->fn_h ); + state_save_register_device_item(device, 0, ST->TA ); + state_save_register_device_item(device, 0, ST->TAC ); + state_save_register_device_item(device, 0, ST->TB ); + state_save_register_device_item(device, 0, ST->TBC ); +} +#endif /* _STATE_H */ + +#if BUILD_OPN +/* write a OPN mode register 0x20-0x2f */ +static void OPNWriteMode(FM_OPN *OPN, int r, int v) +{ + UINT8 c; + FM_CH *CH; + + switch(r) + { + case 0x21: /* Test */ + break; + case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */ + if (v&8) /* LFO enabled ? */ + { + #if 0 + if (!OPN->lfo_timer_overflow) + { + /* restart LFO */ + OPN->lfo_cnt = 0; + OPN->lfo_timer = 0; + OPN->LFO_AM = 0; + OPN->LFO_PM = 0; + } + #endif + + OPN->lfo_timer_overflow = lfo_samples_per_step[v&7] << LFO_SH; + } + else + { + /* Valley Bell: Ported from Genesis Plus GX 1.71 + hold LFO waveform in reset state */ + OPN->lfo_timer_overflow = 0; + OPN->lfo_timer = 0; + OPN->lfo_cnt = 0; + + + OPN->LFO_PM = 0; + OPN->LFO_AM = 126; + /* OPN->lfo_timer_overflow = 0; */ + } + break; + case 0x24: /* timer A High 8*/ + OPN->ST.TA = (OPN->ST.TA & 0x03)|(((int)v)<<2); + break; + case 0x25: /* timer A Low 2*/ + OPN->ST.TA = (OPN->ST.TA & 0x3fc)|(v&3); + break; + case 0x26: /* timer B */ + OPN->ST.TB = (UINT8)v; + break; + case 0x27: /* mode, timer control */ + set_timers( OPN, &(OPN->ST),OPN->ST.param,v ); + break; + case 0x28: /* key on / off */ + c = v & 0x03; + if( c == 3 ) break; + if( (v&0x04) && (OPN->type & TYPE_6CH) ) c+=3; + CH = OPN->P_CH; + CH = &CH[c]; + if(v&0x10) FM_KEYON(OPN,CH,SLOT1); else FM_KEYOFF(OPN,CH,SLOT1); + if(v&0x20) FM_KEYON(OPN,CH,SLOT2); else FM_KEYOFF(OPN,CH,SLOT2); + if(v&0x40) FM_KEYON(OPN,CH,SLOT3); else FM_KEYOFF(OPN,CH,SLOT3); + if(v&0x80) FM_KEYON(OPN,CH,SLOT4); else FM_KEYOFF(OPN,CH,SLOT4); + break; + } +} + +/* write a OPN register (0x30-0xff) */ +static void OPNWriteReg(FM_OPN *OPN, int r, int v) +{ + FM_CH *CH; + FM_SLOT *SLOT; + + UINT8 c = OPN_CHAN(r); + + if (c == 3) return; /* 0xX3,0xX7,0xXB,0xXF */ + + if (r >= 0x100) c+=3; + + CH = OPN->P_CH; + CH = &CH[c]; + + SLOT = &(CH->SLOT[OPN_SLOT(r)]); + + switch( r & 0xf0 ) { + case 0x30: /* DET , MUL */ + set_det_mul(&OPN->ST,CH,SLOT,v); + break; + + case 0x40: /* TL */ + set_tl(CH,SLOT,v); + break; + + case 0x50: /* KS, AR */ + set_ar_ksr(OPN->type,CH,SLOT,v); + break; + + case 0x60: /* bit7 = AM ENABLE, DR */ + set_dr(OPN->type, SLOT,v); + + if(OPN->type & TYPE_LFOPAN) /* YM2608/2610/2610B/2612 */ + { + SLOT->AMmask = (v&0x80) ? ~0 : 0; + } + break; + + case 0x70: /* SR */ + set_sr(OPN->type,SLOT,v); + break; + + case 0x80: /* SL, RR */ + set_sl_rr(OPN->type,SLOT,v); + break; + + case 0x90: /* SSG-EG */ + SLOT->ssg = v&0x0f; + + /* recalculate EG output */ + if (SLOT->state > EG_REL) + { + if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04))) + SLOT->vol_out = ((UINT32)(0x200 - SLOT->volume) & MAX_ATT_INDEX) + SLOT->tl; + else + SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; + } + + /* SSG-EG envelope shapes : + + E AtAlH + 1 0 0 0 \\\\ + + 1 0 0 1 \___ + + 1 0 1 0 \/\/ + ___ + 1 0 1 1 \ + + 1 1 0 0 //// + ___ + 1 1 0 1 / + + 1 1 1 0 /\/\ + + 1 1 1 1 /___ + + + E = SSG-EG enable + + + The shapes are generated using Attack, Decay and Sustain phases. + + Each single character in the diagrams above represents this whole + sequence: + + - when KEY-ON = 1, normal Attack phase is generated (*without* any + difference when compared to normal mode), + + - later, when envelope level reaches minimum level (max volume), + the EG switches to Decay phase (which works with bigger steps + when compared to normal mode - see below), + + - later when envelope level passes the SL level, + the EG swithes to Sustain phase (which works with bigger steps + when compared to normal mode - see below), + + - finally when envelope level reaches maximum level (min volume), + the EG switches to Attack phase again (depends on actual waveform). + + Important is that when switch to Attack phase occurs, the phase counter + of that operator will be zeroed-out (as in normal KEY-ON) but not always. + (I havent found the rule for that - perhaps only when the output level is low) + + The difference (when compared to normal Envelope Generator mode) is + that the resolution in Decay and Sustain phases is 4 times lower; + this results in only 256 steps instead of normal 1024. + In other words: + when SSG-EG is disabled, the step inside of the EG is one, + when SSG-EG is enabled, the step is four (in Decay and Sustain phases). + + Times between the level changes are the same in both modes. + + + Important: + Decay 1 Level (so called SL) is compared to actual SSG-EG output, so + it is the same in both SSG and no-SSG modes, with this exception: + + when the SSG-EG is enabled and is generating raising levels + (when the EG output is inverted) the SL will be found at wrong level !!! + For example, when SL=02: + 0 -6 = -6dB in non-inverted EG output + 96-6 = -90dB in inverted EG output + Which means that EG compares its level to SL as usual, and that the + output is simply inverted afterall. + + + The Yamaha's manuals say that AR should be set to 0x1f (max speed). + That is not necessary, but then EG will be generating Attack phase. + + */ + + + break; + + case 0xa0: + switch( OPN_SLOT(r) ) + { + case 0: /* 0xa0-0xa2 : FNUM1 */ +#ifdef USE_VGM_INIT_SWITCH + if (IsVGMInit) + OPN->ST.fn_h = CH->block_fnum >> 8; +#endif + { + UINT32 fn = (((UINT32)( (OPN->ST.fn_h)&7))<<8) + v; + UINT8 blk = OPN->ST.fn_h>>3; + /* keyscale code */ + CH->kcode = (blk<<2) | opn_fktable[fn >> 7]; + /* phase increment counter */ + CH->fc = OPN->fn_table[fn*2]>>(7-blk); + + /* store fnum in clear form for LFO PM calculations */ + CH->block_fnum = (blk<<11) | fn; + + CH->SLOT[SLOT1].Incr=-1; + } + break; + case 1: /* 0xa4-0xa6 : FNUM2,BLK */ + OPN->ST.fn_h = v&0x3f; +#ifdef USE_VGM_INIT_SWITCH + if (IsVGMInit) // workaround for stupid Kega Fusion init block + CH->block_fnum = (OPN->ST.fn_h << 8) | (CH->block_fnum & 0xFF); +#endif + break; + case 2: /* 0xa8-0xaa : 3CH FNUM1 */ +#ifdef USE_VGM_INIT_SWITCH + if (IsVGMInit) + OPN->SL3.fn_h = OPN->SL3.block_fnum[c] >> 8; +#endif + if(r < 0x100) + { + UINT32 fn = (((UINT32)(OPN->SL3.fn_h&7))<<8) + v; + UINT8 blk = OPN->SL3.fn_h>>3; + /* keyscale code */ + OPN->SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7]; + /* phase increment counter */ + OPN->SL3.fc[c] = OPN->fn_table[fn*2]>>(7-blk); + OPN->SL3.block_fnum[c] = (blk<<11) | fn; + (OPN->P_CH)[2].SLOT[SLOT1].Incr=-1; + } + break; + case 3: /* 0xac-0xae : 3CH FNUM2,BLK */ + if(r < 0x100) + { + OPN->SL3.fn_h = v&0x3f; +#ifdef USE_VGM_INIT_SWITCH + if (IsVGMInit) + OPN->SL3.block_fnum[c] = (OPN->SL3.fn_h << 8) | (OPN->SL3.block_fnum[c] & 0xFF); +#endif + } + break; + } + break; + + case 0xb0: + switch( OPN_SLOT(r) ) + { + case 0: /* 0xb0-0xb2 : FB,ALGO */ + { + unsigned char feedback = ((v>>3)&7); + CH->ALGO = v&7; + CH->FB = feedback ? feedback + 6 : 0; + setup_connection( OPN, CH, c ); + } + break; + case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */ + if( OPN->type & TYPE_LFOPAN) + { + /* b0-2 PMS */ + CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */ + + /* b4-5 AMS */ + CH->ams = lfo_ams_depth_shift[(v>>4) & 0x03]; + + /* PAN : b7 = L, b6 = R */ + OPN->pan[ c*2 ] = (v & 0x80) ? ~0 : 0; + OPN->pan[ c*2+1 ] = (v & 0x40) ? ~0 : 0; + + } + break; + } + break; + } +} + +/* initialize time tables */ +static void init_timetables(FM_OPN *OPN, double freqbase) +{ + int i,d; + double rate; + + /* DeTune table */ + for (d = 0;d <= 3;d++) + { + for (i = 0;i <= 31;i++) + { + rate = ((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 */ + OPN->ST.dt_tab[d][i] = (INT32) rate; + OPN->ST.dt_tab[d+4][i] = -OPN->ST.dt_tab[d][i]; + } + } + + /* there are 2048 FNUMs that can be generated using FNUM/BLK registers + but LFO works with one more bit of a precision so we really need 4096 elements */ + /* calculate fnumber -> increment counter table */ + for(i = 0; i < 4096; i++) + { + /* freq table for octave 7 */ + /* OPN phase increment counter = 20bit */ + /* the correct formula is : F-Number = (144 * fnote * 2^20 / M) / 2^(B-1) */ + /* where sample clock is M/144 */ + /* this means the increment value for one clock sample is FNUM * 2^(B-1) = FNUM * 64 for octave 7 */ + /* we also need to handle the ratio between the chip frequency and the emulated frequency (can be 1.0) */ + OPN->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 */ + } + + /* maximal frequency is required for Phase overflow calculation, register size is 17 bits (Nemesis) */ + OPN->fn_max = (UINT32)( (double)0x20000 * freqbase * (1<<(FREQ_SH-10)) ); +} + +/* prescaler set (and make time tables) */ +static void OPNSetPres(FM_OPN *OPN, int pres, int timer_prescaler, int SSGpres) +{ + /* frequency base */ + OPN->ST.freqbase = (OPN->ST.rate) ? ((double)OPN->ST.clock / OPN->ST.rate) / pres : 0; + + /* EG is updated every 3 samples */ + OPN->eg_timer_add = (UINT32)((1<ST.freqbase); + OPN->eg_timer_overflow = ( 3 ) * (1<lfo_timer_add = (UINT32)((1<ST.freqbase); + + /* Timer base time */ + OPN->ST.timer_prescaler = timer_prescaler; + + /* SSG part prescaler set */ + if( SSGpres ) (*OPN->ST.SSG->set_clock)( OPN->ST.param, OPN->ST.clock * 2 / SSGpres ); + + /* make time tables */ + init_timetables(OPN, OPN->ST.freqbase); +} + +static void reset_channels( FM_ST *ST , FM_CH *CH , int num ) +{ + int c,s; + (void)ST; + + for( c = 0 ; c < num ; c++ ) + { + /* memset(&CH[c], 0x00, sizeof(FM_CH)); */ + CH[c].mem_value = 0; + CH[c].op1_out[0] = 0; + CH[c].op1_out[1] = 0; + CH[c].fc = 0; + for(s = 0 ; s < 4 ; s++ ) + { + /* memset(&CH[c].SLOT[s], 0x00, sizeof(FM_SLOT)); */ + CH[c].SLOT[s].Incr = -1; + CH[c].SLOT[s].key = 0; + CH[c].SLOT[s].phase = 0; + CH[c].SLOT[s].ssg = 0; + CH[c].SLOT[s].ssgn = 0; + CH[c].SLOT[s].state= EG_OFF; + CH[c].SLOT[s].volume = MAX_ATT_INDEX; + CH[c].SLOT[s].vol_out= MAX_ATT_INDEX; + } + } +} + +/* initialize generic tables */ +static void init_tables(void) +{ + signed int i,x; + signed int n; + double o,m; + + /* build Linear Power Table */ + for (x=0; x>= 4; /* 12 bits here */ + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + /* 11 bits here (rounded) */ + n <<= 2; /* 13 bits here (as in real chip) */ + + + /* 14 bits (with sign bit) */ + tl_tab[ x*2 + 0 ] = n; + tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ]; + + /* one entry in the 'Power' table use the following format, xxxxxyyyyyyyys with: */ + /* s = sign bit */ + /* yyyyyyyy = 8-bits decimal part (0-TL_RES_LEN) */ + /* xxxxx = 5-bits integer 'shift' value (0-31) but, since Power table output is 13 bits, */ + /* any value above 13 (included) would be discarded. */ + for (i=1; i<13; i++) + { + tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i; + tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ]; + } + } + + /* build Logarithmic Sinus table */ + for (i=0; i0.0) + o = 8*log(1.0/m)/log(2.0); /* convert to 'decibels' */ + else + o = 8*log(-1.0/m)/log(2.0); /* convert to 'decibels' */ + + o = o / (ENV_STEP/4); + + n = (int)(2.0*o); + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + + /* 13-bits (8.5) value is formatted for above 'Power' table */ + sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); + } + + /* build LFO PM modulation table */ + for(i = 0; i < 8; i++) /* 8 PM depths */ + { + UINT8 fnum; + for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */ + { + UINT8 value; + UINT8 step; + UINT32 offset_depth = i; + UINT32 offset_fnum_bit; + UINT32 bit_tmp; + + for (step=0; step<8; step++) + { + value = 0; + for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */ + { + if (fnum & (1<CH; + FMSAMPLE *bufOut = buffer; + int i; +#if !RSM_ENABLE + FMSAMPLE bufTmp[2]; +#endif + + ym2612_pre_generate(chip); + + if (!frames) + { + update_ssg_eg_channel(&cch[0].SLOT[SLOT1]); + update_ssg_eg_channel(&cch[1].SLOT[SLOT1]); + update_ssg_eg_channel(&cch[2].SLOT[SLOT1]); + update_ssg_eg_channel(&cch[3].SLOT[SLOT1]); + update_ssg_eg_channel(&cch[4].SLOT[SLOT1]); + update_ssg_eg_channel(&cch[5].SLOT[SLOT1]); + } + + /* buffering */ + for(i=0 ; i < frames ; i++) + { +#if RSM_ENABLE + while(F2612->OPN.ST.framecnt >= F2612->OPN.ST.rateratio)/* Copy-Pasta from Nuked */ + { + /* Copy-Pasta from Nuked */ + F2612->OPN.ST.prev_sample[0] = F2612->OPN.ST.cur_sample[0]; + F2612->OPN.ST.prev_sample[1] = F2612->OPN.ST.cur_sample[1]; + ym2612_generate_one_native(chip, F2612->OPN.ST.cur_sample); + F2612->OPN.ST.framecnt -= F2612->OPN.ST.rateratio; + /* Copy-Pasta from Nuked */ + } + if (mix) + { + *bufOut++ += (FMSAMPLE)((F2612->OPN.ST.prev_sample[0] * (F2612->OPN.ST.rateratio - F2612->OPN.ST.framecnt) + + F2612->OPN.ST.cur_sample[0] * F2612->OPN.ST.framecnt) / F2612->OPN.ST.rateratio); + *bufOut++ += (FMSAMPLE)((F2612->OPN.ST.prev_sample[1] * (F2612->OPN.ST.rateratio - F2612->OPN.ST.framecnt) + + F2612->OPN.ST.cur_sample[1] * F2612->OPN.ST.framecnt) / F2612->OPN.ST.rateratio); + } else { + *bufOut++ = (FMSAMPLE)((F2612->OPN.ST.prev_sample[0] * (F2612->OPN.ST.rateratio - F2612->OPN.ST.framecnt) + + F2612->OPN.ST.cur_sample[0] * F2612->OPN.ST.framecnt) / F2612->OPN.ST.rateratio); + *bufOut++ = (FMSAMPLE)((F2612->OPN.ST.prev_sample[1] * (F2612->OPN.ST.rateratio - F2612->OPN.ST.framecnt) + + F2612->OPN.ST.cur_sample[1] * F2612->OPN.ST.framecnt) / F2612->OPN.ST.rateratio); + } + F2612->OPN.ST.framecnt += 1 << RSM_FRAC; +#else + if (mix) + { + ym2612_generate_one_native(chip, bufTmp); + bufOut[0] += bufTmp[0]; + bufOut[1] += bufTmp[1]; + } + else + { + ym2612_generate_one_native(chip, bufOut); + } + bufOut += 2; +#endif + } + /* ym2612_post_generate(chip, frames); */ +} + +void ym2612_pre_generate(void *chip) +{ + YM2612 *F2612 = (YM2612 *)chip; + FM_OPN *OPN = &F2612->OPN; + FM_CH *cch = F2612->CH; + + /* refresh PG and EG */ + refresh_fc_eg_chan( OPN, &cch[0] ); + refresh_fc_eg_chan( OPN, &cch[1] ); + if( (OPN->ST.mode & 0xc0) ) + { + /* 3SLOT MODE */ + if( cch[2].SLOT[SLOT1].Incr==-1) + { + refresh_fc_eg_slot(OPN, &cch[2].SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] ); + refresh_fc_eg_slot(OPN, &cch[2].SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] ); + refresh_fc_eg_slot(OPN, &cch[2].SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] ); + refresh_fc_eg_slot(OPN, &cch[2].SLOT[SLOT4] , cch[2].fc , cch[2].kcode ); + } + } else + refresh_fc_eg_chan( OPN, &cch[2] ); + refresh_fc_eg_chan( OPN, &cch[3] ); + refresh_fc_eg_chan( OPN, &cch[4] ); + refresh_fc_eg_chan( OPN, &cch[5] ); +} + +void ym2612_generate_one_native(void *chip, FMSAMPLE buffer[]) +{ + YM2612 *F2612 = (YM2612 *)chip; + FM_OPN *OPN = &F2612->OPN; + INT32 *out_fm = OPN->out_fm; + FM_CH *cch = F2612->CH; + INT32 dacout; + int lt,rt; + + if (! F2612->MuteDAC) + dacout = F2612->dacout; + else + dacout = 0; + + /* clear outputs */ + out_fm[0] = 0; + out_fm[1] = 0; + out_fm[2] = 0; + out_fm[3] = 0; + out_fm[4] = 0; + out_fm[5] = 0; + + /* update SSG-EG output */ + update_ssg_eg_channel(&cch[0].SLOT[SLOT1]); + update_ssg_eg_channel(&cch[1].SLOT[SLOT1]); + update_ssg_eg_channel(&cch[2].SLOT[SLOT1]); + update_ssg_eg_channel(&cch[3].SLOT[SLOT1]); + update_ssg_eg_channel(&cch[4].SLOT[SLOT1]); + update_ssg_eg_channel(&cch[5].SLOT[SLOT1]); + + /* calculate FM */ + if (! F2612->dac_test) + { + chan_calc(F2612, OPN, &cch[0]); + chan_calc(F2612, OPN, &cch[1]); + chan_calc(F2612, OPN, &cch[2]); + chan_calc(F2612, OPN, &cch[3]); + chan_calc(F2612, OPN, &cch[4]); + if( F2612->dacen ) + cch[5].connect4 += dacout; + else + chan_calc(F2612, OPN, &cch[5]); + } + else + { + out_fm[0] = out_fm[1] = dacout; + out_fm[2] = out_fm[3] = dacout; + out_fm[5] = dacout; + } + + /* advance LFO */ + advance_lfo(OPN); + + /* advance envelope generator */ + OPN->eg_timer += OPN->eg_timer_add; + while (OPN->eg_timer >= OPN->eg_timer_overflow) + { + /* reset EG timer */ + OPN->eg_timer -= OPN->eg_timer_overflow; + /* increment EG counter */ + OPN->eg_cnt++; + /* EG counter is 12-bit only and zero value is skipped (verified on real hardware) */ + if (OPN->eg_cnt == 4096) + OPN->eg_cnt = 1; + + /* advance envelope generator */ + advance_eg_channel(OPN, &cch[0].SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[1].SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[2].SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[3].SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[4].SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[5].SLOT[SLOT1]); + } + + /*fprintf(hFile, "%u", FileSample, out_fm[0]); + for (lt = 0; lt < 6; lt ++) + fprintf(hFile, "\t%d", out_fm[lt]); + fprintf(hFile, "\n"); + FileSample ++;*/ + + if (out_fm[0] > 8192) out_fm[0] = 8192; + else if (out_fm[0] < -8192) out_fm[0] = -8192; + if (out_fm[1] > 8192) out_fm[1] = 8192; + else if (out_fm[1] < -8192) out_fm[1] = -8192; + if (out_fm[2] > 8192) out_fm[2] = 8192; + else if (out_fm[2] < -8192) out_fm[2] = -8192; + if (out_fm[3] > 8192) out_fm[3] = 8192; + else if (out_fm[3] < -8192) out_fm[3] = -8192; + if (out_fm[4] > 8192) out_fm[4] = 8192; + else if (out_fm[4] < -8192) out_fm[4] = -8192; + if (out_fm[5] > 8192) out_fm[5] = 8192; + else if (out_fm[5] < -8192) out_fm[5] = -8192; + + /* 6-channels mixing */ + lt = ((out_fm[0]>>0) & OPN->pan[0]); + rt = ((out_fm[0]>>0) & OPN->pan[1]); + lt += ((out_fm[1]>>0) & OPN->pan[2]); + rt += ((out_fm[1]>>0) & OPN->pan[3]); + lt += ((out_fm[2]>>0) & OPN->pan[4]); + rt += ((out_fm[2]>>0) & OPN->pan[5]); + lt += ((out_fm[3]>>0) & OPN->pan[6]); + rt += ((out_fm[3]>>0) & OPN->pan[7]); + if (! F2612->dac_test) + { + lt += ((out_fm[4]>>0) & OPN->pan[8]); + rt += ((out_fm[4]>>0) & OPN->pan[9]); + } + else + { + lt += dacout; + lt += dacout; + } + lt += ((out_fm[5]>>0) & OPN->pan[10]); + rt += ((out_fm[5]>>0) & OPN->pan[11]); + + /* Limit( lt, MAXOUT, MINOUT ); */ + /* Limit( rt, MAXOUT, MINOUT ); */ + + #ifdef SAVE_SAMPLE + SAVE_ALL_CHANNELS + #endif + + /* buffering */ + if (F2612->WaveOutMode & 0x01) + F2612->WaveL = lt; + if (F2612->WaveOutMode & 0x02) + F2612->WaveR = rt; + if (F2612->WaveOutMode ^ 0x03) + F2612->WaveOutMode ^= 0x03; + + buffer[0] = (FMSAMPLE)(F2612->WaveL / 2); + buffer[1] = (FMSAMPLE)(F2612->WaveR / 2); + + /* CSM mode: if CSM Key ON has occured, CSM Key OFF need to be sent */ + /* only if Timer A does not overflow again (i.e CSM Key ON not set again) */ + OPN->SL3.key_csm <<= 1; + + /* timer A control */ + /* INTERNAL_TIMER_A( &OPN->ST , cch[2] ) */ + { + if( OPN->ST.TAC && (OPN->ST.timer_handler==0) ) + if( (OPN->ST.TAC -= (int)(OPN->ST.freqbase*4096)) <= 0 ) + { + TimerAOver( &OPN->ST ); + /* CSM mode total level latch and auto key on */ + if( OPN->ST.mode & 0x80 ) + CSMKeyControll( OPN, &cch[2] ); + } + } + + /* CSM Mode Key ON still disabled */ + if (OPN->SL3.key_csm & 2) + { + /* CSM Mode Key OFF (verified by Nemesis on real hardware) */ + FM_KEYOFF_CSM(&cch[2],SLOT1); + FM_KEYOFF_CSM(&cch[2],SLOT2); + FM_KEYOFF_CSM(&cch[2],SLOT3); + FM_KEYOFF_CSM(&cch[2],SLOT4); + OPN->SL3.key_csm = 0; + } +} + +#if 0 +void ym2612_post_generate(void *chip, int length) +{ + YM2612 *F2612 = (YM2612 *)chip; + /* timer B control */ + INTERNAL_TIMER_B(&F2612->OPN.ST, length); +} +#endif + +#ifdef __STATE_H__ +void ym2612_postload(void *chip) +{ + if (chip) + { + YM2612 *F2612 = (YM2612 *)chip; + int r; + + /* DAC data & port */ + F2612->dacout = ((int)F2612->REGS[0x2a] - 0x80) << 6; /* level unknown */ + F2612->dacen = F2612->REGS[0x2d] & 0x80; + /* OPN registers */ + /* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */ + for(r=0x30;r<0x9e;r++) + if((r&3) != 3) + { + OPNWriteReg(&F2612->OPN,r,F2612->REGS[r]); + OPNWriteReg(&F2612->OPN,r|0x100,F2612->REGS[r|0x100]); + } + /* FB / CONNECT , L / R / AMS / PMS */ + for(r=0xb0;r<0xb6;r++) + if((r&3) != 3) + { + OPNWriteReg(&F2612->OPN,r,F2612->REGS[r]); + OPNWriteReg(&F2612->OPN,r|0x100,F2612->REGS[r|0x100]); + } + /* channels */ + /*FM_channel_postload(F2612->CH,6);*/ + } +} + +static void YM2612_save_state(YM2612 *F2612, running_device *device) +{ + state_save_register_device_item_array(device, 0, F2612->REGS); + FMsave_state_st(device,&F2612->OPN.ST); + FMsave_state_channel(device,F2612->CH,6); + /* 3slots */ + state_save_register_device_item_array(device, 0, F2612->OPN.SL3.fc); + state_save_register_device_item(device, 0, F2612->OPN.SL3.fn_h); + state_save_register_device_item_array(device, 0, F2612->OPN.SL3.kcode); + /* address register1 */ + state_save_register_device_item(device, 0, F2612->addr_A1); +} +#endif /* _STATE_H */ + +/* initialize YM2612 emulator(s) */ +/* void * ym2612_init(void *param, running_device *device, int clock, int rate, + FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler) */ +void * ym2612_init(void *param, int clock, int rate, + FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler) +{ + YM2612 *F2612; + + if (clock <= 0 || rate <= 0) + return NULL; /* Forbid zero clock and sample rate */ + + /* allocate extend state space */ + /* F2612 = auto_alloc_clear(device->machine, YM2612); */ + F2612 = (YM2612 *)malloc(sizeof(YM2612)); + if (F2612 == NULL) + return NULL; + memset(F2612, 0x00, sizeof(YM2612)); + /* allocate total level table (128kb space) */ + init_tables(); + + F2612->OPN.ST.param = param; + F2612->OPN.type = TYPE_YM2612; + F2612->OPN.P_CH = F2612->CH; + /* F2612->OPN.ST.device = device; */ + F2612->OPN.ST.clock = clock; +#if RSM_ENABLE + F2612->OPN.ST.rate = 53267; + F2612->OPN.ST.rateratio = (INT32)(UINT32)((((UINT64)144 * rate) << RSM_FRAC) / clock); + F2612->OPN.ST.framecnt = 1 << RSM_FRAC; + memset(&(F2612->OPN.ST.cur_sample), 0x00, sizeof(FMSAMPLE) * 2); + memset(&(F2612->OPN.ST.prev_sample), 0x00, sizeof(FMSAMPLE) * 2); +#else + F2612->OPN.ST.rate = rate; +#endif + /* F2612->OPN.ST.irq = 0; */ + /* F2612->OPN.ST.status = 0; */ + /* Extend handler */ + F2612->OPN.ST.timer_handler = timer_handler; + F2612->OPN.ST.IRQ_Handler = IRQHandler; + + if (PseudoSt) + F2612->WaveOutMode = 0x01; + else + F2612->WaveOutMode = 0x03; + /*hFile = fopen("YM2612.log", "wt"); + fprintf(hFile, "Clock: %d, Sample Rate: %d\n", clock, rate); + fprintf(hFile, "Sample\tCh 0\tCh 1\tCh 2\tCh 3\tCh 4\tCh 5\n"); + FileSample = 0;*/ + +#ifdef __STATE_H__ + YM2612_save_state(F2612, device); +#endif + return F2612; +} + +/* shut down emulator */ +void ym2612_shutdown(void *chip) +{ + YM2612 *F2612 = (YM2612 *)chip; + /* fclose(hFile); */ + + FMCloseTable(); + /* auto_free(F2612->OPN.ST.device->machine, F2612); */ + free(F2612); +} + +/* reset one of chip */ +void ym2612_reset_chip(void *chip) +{ + int i; + YM2612 *F2612 = (YM2612 *)chip; + FM_OPN *OPN = &F2612->OPN; + + OPNSetPres( OPN, 6*24, 6*24, 0); + /* status clear */ + FM_IRQMASK_SET(&OPN->ST,0x03); + FM_BUSY_CLEAR(&OPN->ST); + /* OPNWriteMode(OPN,0x27,0x30); */ /* mode 0 , timer reset */ + +#if RSM_ENABLE + /* Resampler's state */ + F2612->OPN.ST.framecnt = 1 << RSM_FRAC; + memset(&(F2612->OPN.ST.cur_sample), 0x00, sizeof(FMSAMPLE) * 2); + memset(&(F2612->OPN.ST.prev_sample), 0x00, sizeof(FMSAMPLE) * 2); +#endif + + OPN->eg_timer = 0; + OPN->eg_cnt = 0; + + OPN->lfo_timer = 0; + OPN->lfo_cnt = 0; + OPN->LFO_AM = 126; + OPN->LFO_PM = 0; + + OPN->ST.TAC = 0; + OPN->ST.TBC = 0; + + OPN->SL3.key_csm = 0; + + OPN->ST.status = 0; + OPN->ST.mode = 0; + + memset(F2612->REGS, 0x00, sizeof(UINT8) * 512); + + OPNWriteMode(OPN,0x22,0x00); + + OPNWriteMode(OPN,0x27,0x30); + OPNWriteMode(OPN,0x26,0x00); + OPNWriteMode(OPN,0x25,0x00); + OPNWriteMode(OPN,0x24,0x00); + + reset_channels( &OPN->ST , &F2612->CH[0] , 6 ); + + for(i = 0xb6 ; i >= 0xb4 ; i-- ) + { + OPNWriteReg(OPN,i ,0xc0); + OPNWriteReg(OPN,i|0x100,0xc0); + } + for(i = 0xb2 ; i >= 0x30 ; i-- ) + { + OPNWriteReg(OPN,i ,0); + OPNWriteReg(OPN,i|0x100,0); + } + + /* DAC mode clear */ + F2612->dacen = 0; + F2612->dac_test = 0; + F2612->dacout = 0; + + if (F2612->WaveOutMode == 0x02) + F2612->WaveOutMode >>= 1; +} + +/* YM2612 write */ +/* n = number */ +/* a = address */ +/* v = value */ +int ym2612_write(void *chip, int a, UINT8 v) +{ + YM2612 *F2612 = (YM2612 *)chip; + int addr; + + v &= 0xff; /* adjust to 8 bit bus */ + + switch( a&3) + { + case 0: /* address port 0 */ + F2612->OPN.ST.address = v; + F2612->addr_A1 = 0; + break; + + case 1: /* data port 0 */ + if (F2612->addr_A1 != 0) + break; /* verified on real YM2608 */ + + addr = F2612->OPN.ST.address; + F2612->REGS[addr] = v; + switch( addr & 0xf0 ) + { + case 0x20: /* 0x20-0x2f Mode */ + switch( addr ) + { + case 0x2a: /* DAC data (YM2612) */ + ym2612_update_one(chip, DUMMYBUF, 0); + F2612->dacout = ((int)v - 0x80) << 6; /* level unknown */ + break; + case 0x2b: /* DAC Sel (YM2612) */ + /* b7 = dac enable */ + F2612->dacen = v & 0x80; + break; + case 0x2C: /* undocumented: DAC Test Reg */ + /* b5 = volume enable */ + F2612->dac_test = v & 0x20; + break; + default: /* OPN section */ + /* ym2612_update_req(F2612->OPN.ST.param); */ + ym2612_update_one(chip, DUMMYBUF, 0); + /* write register */ + OPNWriteMode(&(F2612->OPN),addr,v); + } + break; + default: /* 0x30-0xff OPN section */ + ym2612_update_one(chip, DUMMYBUF, 0); + /* write register */ + OPNWriteReg(&(F2612->OPN),addr,v); + } + break; + + case 2: /* address port 1 */ + F2612->OPN.ST.address = v; + F2612->addr_A1 = 1; + break; + + case 3: /* data port 1 */ + if (F2612->addr_A1 != 1) + break; /* verified on real YM2608 */ + + addr = F2612->OPN.ST.address; + F2612->REGS[addr | 0x100] = v; + ym2612_update_one(chip, DUMMYBUF, 0); + OPNWriteReg(&(F2612->OPN),addr | 0x100,v); + break; + } + return F2612->OPN.ST.irq; +} + +UINT8 ym2612_read(void *chip,int a) +{ + YM2612 *F2612 = (YM2612 *)chip; + + switch( a&3) + { + case 0: /* status 0 */ + return FM_STATUS_FLAG(&F2612->OPN.ST); + case 1: + case 2: + case 3: + /* LOG(LOG_WAR,("YM2612 #%p:A=%d read unmapped area\n",F2612->OPN.ST.param,a)); */ + return FM_STATUS_FLAG(&F2612->OPN.ST); + } + return 0; +} + +int ym2612_timer_over(void *chip,int c) +{ + YM2612 *F2612 = (YM2612 *)chip; + + if( c ) + { /* Timer B */ + TimerBOver( &(F2612->OPN.ST) ); + } + else + { /* Timer A */ + ym2612_update_one(chip, DUMMYBUF, 0); + /* timer update */ + TimerAOver( &(F2612->OPN.ST) ); + /* CSM mode key,TL controll */ + if ((F2612->OPN.ST.mode & 0xc0) == 0x80) + { /* CSM mode total level latch and auto key on */ + CSMKeyControll( &F2612->OPN, &(F2612->CH[2]) ); + } + } + return F2612->OPN.ST.irq; +} + + +void ym2612_set_mutemask(void *chip, UINT32 MuteMask) +{ + YM2612 *F2612 = (YM2612 *)chip; + UINT8 CurChn; + + for (CurChn = 0; CurChn < 6; CurChn ++) + F2612->CH[CurChn].Muted = (MuteMask >> CurChn) & 0x01; + F2612->MuteDAC = (MuteMask >> 6) & 0x01; + + return; +} + +void ym2612_setoptions(UINT8 Flags) +{ + PseudoSt = (Flags >> 2) & 0x01; + + return; +} +#endif /* (BUILD_YM2612||BUILD_YM3238) */ diff --git a/src/sound/opnmidi/chips/mame/mame_ym2612fm.h b/src/sound/opnmidi/chips/mame/mame_ym2612fm.h new file mode 100644 index 000000000..de05236ef --- /dev/null +++ b/src/sound/opnmidi/chips/mame/mame_ym2612fm.h @@ -0,0 +1,164 @@ +/* + File: fm.h -- header file for software emulation for FM sound generator + +*/ + +#ifndef FM_HHHHH +#define FM_HHHHH + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mamedef.h" + +/* --- select emulation chips --- */ +/* +#define BUILD_YM2203 (HAS_YM2203) // build YM2203(OPN) emulator +#define BUILD_YM2608 (HAS_YM2608) // build YM2608(OPNA) emulator +#define BUILD_YM2610 (HAS_YM2610) // build YM2610(OPNB) emulator +#define BUILD_YM2610B (HAS_YM2610B) // build YM2610B(OPNB?)emulator +#define BUILD_YM2612 (HAS_YM2612) // build YM2612(OPN2) emulator +#define BUILD_YM3438 (HAS_YM3438) // build YM3438(OPN) emulator +*/ +#define BUILD_YM2203 0 +#define BUILD_YM2608 0 +#define BUILD_YM2610 0 +#define BUILD_YM2610B 0 +#define BUILD_YM2612 1 +#define BUILD_YM3438 0 + +#define FM_BUSY_FLAG_SUPPORT 0 + +/* select bit size of output : 8 or 16 */ +#define FM_SAMPLE_BITS 16 + +/* select timer system internal or external */ +#define FM_INTERNAL_TIMER 1 + +/* --- speedup optimize --- */ +/* busy flag enulation , The definition of FM_GET_TIME_NOW() is necessary. */ +/* #define FM_BUSY_FLAG_SUPPORT 1 */ + +/* --- external SSG(YM2149/AY-3-8910)emulator interface port */ +/* used by YM2203,YM2608,and YM2610 */ +typedef struct _ssg_callbacks ssg_callbacks; +struct _ssg_callbacks +{ + void (*set_clock)(void *param, int clock); + void (*write)(void *param, int address, int data); + int (*read)(void *param); + void (*reset)(void *param); +}; + +/* --- external callback funstions for realtime update --- */ + +#if FM_BUSY_FLAG_SUPPORT +#define TIME_TYPE attotime +#define UNDEFINED_TIME attotime_zero +#define FM_GET_TIME_NOW(machine) timer_get_time(machine) +#define ADD_TIMES(t1, t2) attotime_add((t1), (t2)) +#define COMPARE_TIMES(t1, t2) attotime_compare((t1), (t2)) +#define MULTIPLY_TIME_BY_INT(t,i) attotime_mul(t, i) +#endif + +/* compiler dependence */ +#if 0 +#ifndef OSD_CPU_H +#define OSD_CPU_H +typedef unsigned char UINT8; /* unsigned 8bit */ +typedef unsigned short UINT16; /* unsigned 16bit */ +typedef unsigned int UINT32; /* unsigned 32bit */ +typedef signed char INT8; /* signed 8bit */ +typedef signed short INT16; /* signed 16bit */ +typedef signed int INT32; /* signed 32bit */ +#endif /* OSD_CPU_H */ +#endif + + + +typedef stream_sample_t FMSAMPLE; +/* +#if (FM_SAMPLE_BITS==16) +typedef INT16 FMSAMPLE; +#endif +#if (FM_SAMPLE_BITS==8) +typedef unsigned char FMSAMPLE; +#endif +*/ + +typedef void (*FM_TIMERHANDLER)(void *param,int c,int cnt,int clock); +typedef void (*FM_IRQHANDLER)(void *param,int irq); +/* FM_TIMERHANDLER : Stop or Start timer */ +/* int n = chip number */ +/* int c = Channel 0=TimerA,1=TimerB */ +/* int count = timer count (0=stop) */ +/* doube stepTime = step time of one count (sec.)*/ + +/* FM_IRQHHANDLER : IRQ level changing sense */ +/* int n = chip number */ +/* int irq = IRQ level 0=OFF,1=ON */ + +#if (BUILD_YM2612||BUILD_YM3438) + +/** + * @brief Initialize chip and return the instance + * @param param Unused, keep NULL + * @param baseclock YM2612 clock + * @param rate Output sample rate + * @param TimerHandler Keep NULL + * @param IRQHandler Keep NULL + * @return Chip instance or NULL on any error + */ +void * ym2612_init(void *param, int baseclock, int rate, + FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler); +/** + * @brief Free chip instance + * @param chip Chip instance + */ +void ym2612_shutdown(void *chip); +/** + * @brief Reset state of the chip + * @param chip Chip instance + */ +void ym2612_reset_chip(void *chip); +/** + * @brief Generate stereo output of specified length + * @param chip Chip instance + * @param buffer Output sound buffer + * @param frames Output buffer size in frames (one frame - two array entries of the buffer) + * @param mix 0 - override buffer data, 1 - mix output data with a content of the buffer + */ +void ym2612_generate(void *chip, FMSAMPLE *buffer, int frames, int mix); +#define ym2612_update_one(chip, buffer, length) ym2612_generate(chip, buffer, length, 0) + +/** + * @brief Single-Sample generation prepare + * @param chip Chip instance + */ +void ym2612_pre_generate(void *chip); +/** + * @brief Generate single stereo PCM frame. Will be used native sample rate of 53267 Hz + * @param chip Chip instance + * @param buffer One stereo PCM frame + */ +void ym2612_generate_one_native(void *chip, FMSAMPLE buffer[2]); + +/* void ym2612_post_generate(void *chip, int length); */ + +int ym2612_write(void *chip, int a,unsigned char v); +unsigned char ym2612_read(void *chip,int a); +int ym2612_timer_over(void *chip, int c ); +void ym2612_postload(void *chip); + +void ym2612_set_mutemask(void *chip, UINT32 MuteMask); +void ym2612_setoptions(UINT8 Flags); +#endif /* (BUILD_YM2612||BUILD_YM3438) */ + +#ifdef __cplusplus +} +#endif + +#endif /* FM_HHHHH */ diff --git a/src/sound/opnmidi/chips/mame/mamedef.h b/src/sound/opnmidi/chips/mame/mamedef.h new file mode 100644 index 000000000..efed080b8 --- /dev/null +++ b/src/sound/opnmidi/chips/mame/mamedef.h @@ -0,0 +1,65 @@ +#ifndef MAMEDEF_H_ +#define MAMEDEF_H_ + +/* typedefs to use MAME's (U)INTxx types (copied from MAME\src\ods\odscomm.h) */ +/* 8-bit values */ +typedef unsigned char UINT8; +typedef signed char INT8; + +/* 16-bit values */ +typedef unsigned short UINT16; +typedef signed short INT16; + +/* 32-bit values */ +#ifndef _WINDOWS_H +typedef unsigned int UINT32; +typedef signed int INT32; +#endif + +/* 64-bit values */ +#ifndef _WINDOWS_H +#ifdef _MSC_VER +typedef signed __int64 INT64; +typedef unsigned __int64 UINT64; +#else +__extension__ typedef unsigned long long UINT64; +__extension__ typedef signed long long INT64; +#endif +#endif + +/* offsets and addresses are 32-bit (for now...) */ +typedef UINT32 offs_t; + +/* stream_sample_t is used to represent a single sample in a sound stream */ +typedef INT16 stream_sample_t; + +#if defined(VGM_BIG_ENDIAN) +#define BYTE_XOR_BE(x) (x) +#elif defined(VGM_LITTLE_ENDIAN) +#define BYTE_XOR_BE(x) ((x) ^ 0x01) +#else +/* don't define BYTE_XOR_BE so that it throws an error when compiling */ +#endif + +#if defined(_MSC_VER) +//#define INLINE static __forceinline +#define INLINE static __inline +#elif defined(__GNUC__) +#define INLINE static __inline__ +#else +#define INLINE static inline +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifdef _DEBUG +#define logerror printf +#else +#define logerror +#endif + +typedef void (*SRATE_CALLBACK)(void*, UINT32); + +#endif /* __MAMEDEF_H__ */ diff --git a/src/sound/opnmidi/chips/mame_opn2.cpp b/src/sound/opnmidi/chips/mame_opn2.cpp new file mode 100644 index 000000000..e9533131f --- /dev/null +++ b/src/sound/opnmidi/chips/mame_opn2.cpp @@ -0,0 +1,54 @@ +#include "mame_opn2.h" +#include "mame/mame_ym2612fm.h" +#include +#include + +MameOPN2::MameOPN2() +{ + chip = NULL; + setRate(m_rate, m_clock); +} + +MameOPN2::~MameOPN2() +{ + ym2612_shutdown(chip); +} + +void MameOPN2::setRate(uint32_t rate, uint32_t clock) +{ + OPNChipBaseT::setRate(rate, clock); + if(chip) + ym2612_shutdown(chip); + uint32_t chipRate = isRunningAtPcmRate() ? rate : static_cast(nativeRate); + chip = ym2612_init(NULL, (int)clock, (int)chipRate, NULL, NULL); + ym2612_reset_chip(chip); +} + +void MameOPN2::reset() +{ + OPNChipBaseT::reset(); + ym2612_reset_chip(chip); +} + +void MameOPN2::writeReg(uint32_t port, uint16_t addr, uint8_t data) +{ + ym2612_write(chip, 0 + (int)(port) * 2, (uint8_t)addr); + ym2612_write(chip, 1 + (int)(port) * 2, data); +} + +void MameOPN2::nativePreGenerate() +{ + void *chip = this->chip; + ym2612_pre_generate(chip); +} + +void MameOPN2::nativeGenerate(int16_t *frame) +{ + void *chip = this->chip; + ym2612_generate_one_native(chip, frame); +} + +const char *MameOPN2::emulatorName() +{ + return "MAME YM2612"; +} diff --git a/src/sound/opnmidi/chips/mame_opn2.h b/src/sound/opnmidi/chips/mame_opn2.h new file mode 100644 index 000000000..832602476 --- /dev/null +++ b/src/sound/opnmidi/chips/mame_opn2.h @@ -0,0 +1,23 @@ +#ifndef MAME_OPN2_H +#define MAME_OPN2_H + +#include "opn_chip_base.h" + +class MameOPN2 final : public OPNChipBaseT +{ + void *chip; +public: + MameOPN2(); + ~MameOPN2() override; + + bool canRunAtPcmRate() const override { return true; } + void setRate(uint32_t rate, uint32_t clock) override; + void reset() override; + void writeReg(uint32_t port, uint16_t addr, uint8_t data) override; + void nativePreGenerate() override; + void nativePostGenerate() override {} + void nativeGenerate(int16_t *frame) override; + const char *emulatorName() override; +}; + +#endif // MAME_OPN2_H diff --git a/src/sound/opnmidi/chips/nuked/ym3438.c b/src/sound/opnmidi/chips/nuked/ym3438.c new file mode 100644 index 000000000..019ca4cde --- /dev/null +++ b/src/sound/opnmidi/chips/nuked/ym3438.c @@ -0,0 +1,1592 @@ +/* + * Copyright (C) 2017 Alexey Khokholov (Nuke.YKT) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + * Nuked OPN2(Yamaha YM3438) emulator. + * Thanks: + * Silicon Pr0n: + * Yamaha YM3438 decap and die shot(digshadow). + * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): + * OPL2 ROMs. + * + * version: 1.0.7 + */ + +#include +#include "ym3438.h" + +enum { + eg_num_attack = 0, + eg_num_decay = 1, + eg_num_sustain = 2, + eg_num_release = 3 +}; + +/* logsin table */ +static const Bit16u logsinrom[256] = { + 0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471, + 0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365, + 0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd, + 0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261, + 0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f, + 0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd, + 0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195, + 0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166, + 0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c, + 0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118, + 0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8, + 0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db, + 0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1, + 0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9, + 0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094, + 0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081, + 0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070, + 0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060, + 0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052, + 0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045, + 0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039, + 0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f, + 0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026, + 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e, + 0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017, + 0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011, + 0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c, + 0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007, + 0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004, + 0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002, + 0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 +}; + +/* exp table */ +static const Bit16u exprom[256] = { + 0x000, 0x003, 0x006, 0x008, 0x00b, 0x00e, 0x011, 0x014, + 0x016, 0x019, 0x01c, 0x01f, 0x022, 0x025, 0x028, 0x02a, + 0x02d, 0x030, 0x033, 0x036, 0x039, 0x03c, 0x03f, 0x042, + 0x045, 0x048, 0x04b, 0x04e, 0x051, 0x054, 0x057, 0x05a, + 0x05d, 0x060, 0x063, 0x066, 0x069, 0x06c, 0x06f, 0x072, + 0x075, 0x078, 0x07b, 0x07e, 0x082, 0x085, 0x088, 0x08b, + 0x08e, 0x091, 0x094, 0x098, 0x09b, 0x09e, 0x0a1, 0x0a4, + 0x0a8, 0x0ab, 0x0ae, 0x0b1, 0x0b5, 0x0b8, 0x0bb, 0x0be, + 0x0c2, 0x0c5, 0x0c8, 0x0cc, 0x0cf, 0x0d2, 0x0d6, 0x0d9, + 0x0dc, 0x0e0, 0x0e3, 0x0e7, 0x0ea, 0x0ed, 0x0f1, 0x0f4, + 0x0f8, 0x0fb, 0x0ff, 0x102, 0x106, 0x109, 0x10c, 0x110, + 0x114, 0x117, 0x11b, 0x11e, 0x122, 0x125, 0x129, 0x12c, + 0x130, 0x134, 0x137, 0x13b, 0x13e, 0x142, 0x146, 0x149, + 0x14d, 0x151, 0x154, 0x158, 0x15c, 0x160, 0x163, 0x167, + 0x16b, 0x16f, 0x172, 0x176, 0x17a, 0x17e, 0x181, 0x185, + 0x189, 0x18d, 0x191, 0x195, 0x199, 0x19c, 0x1a0, 0x1a4, + 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4, + 0x1c8, 0x1cc, 0x1d0, 0x1d4, 0x1d8, 0x1dc, 0x1e0, 0x1e4, + 0x1e8, 0x1ec, 0x1f0, 0x1f5, 0x1f9, 0x1fd, 0x201, 0x205, + 0x209, 0x20e, 0x212, 0x216, 0x21a, 0x21e, 0x223, 0x227, + 0x22b, 0x230, 0x234, 0x238, 0x23c, 0x241, 0x245, 0x249, + 0x24e, 0x252, 0x257, 0x25b, 0x25f, 0x264, 0x268, 0x26d, + 0x271, 0x276, 0x27a, 0x27f, 0x283, 0x288, 0x28c, 0x291, + 0x295, 0x29a, 0x29e, 0x2a3, 0x2a8, 0x2ac, 0x2b1, 0x2b5, + 0x2ba, 0x2bf, 0x2c4, 0x2c8, 0x2cd, 0x2d2, 0x2d6, 0x2db, + 0x2e0, 0x2e5, 0x2e9, 0x2ee, 0x2f3, 0x2f8, 0x2fd, 0x302, + 0x306, 0x30b, 0x310, 0x315, 0x31a, 0x31f, 0x324, 0x329, + 0x32e, 0x333, 0x338, 0x33d, 0x342, 0x347, 0x34c, 0x351, + 0x356, 0x35b, 0x360, 0x365, 0x36a, 0x370, 0x375, 0x37a, + 0x37f, 0x384, 0x38a, 0x38f, 0x394, 0x399, 0x39f, 0x3a4, + 0x3a9, 0x3ae, 0x3b4, 0x3b9, 0x3bf, 0x3c4, 0x3c9, 0x3cf, + 0x3d4, 0x3da, 0x3df, 0x3e4, 0x3ea, 0x3ef, 0x3f5, 0x3fa +}; + +/* Note table */ +static const Bit32u fn_note[16] = { + 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3 +}; + +/* Envelope generator */ +static const Bit32u eg_stephi[4][4] = { + { 0, 0, 0, 0 }, + { 1, 0, 0, 0 }, + { 1, 0, 1, 0 }, + { 1, 1, 1, 0 } +}; + +static const Bit8u eg_am_shift[4] = { + 7, 3, 1, 0 +}; + +/* Phase generator */ +static const Bit32u pg_detune[8] = { 16, 17, 19, 20, 22, 24, 27, 29 }; + +static const Bit32u pg_lfo_sh1[8][8] = { + { 7, 7, 7, 7, 7, 7, 7, 7 }, + { 7, 7, 7, 7, 7, 7, 7, 7 }, + { 7, 7, 7, 7, 7, 7, 1, 1 }, + { 7, 7, 7, 7, 1, 1, 1, 1 }, + { 7, 7, 7, 1, 1, 1, 1, 0 }, + { 7, 7, 1, 1, 0, 0, 0, 0 }, + { 7, 7, 1, 1, 0, 0, 0, 0 }, + { 7, 7, 1, 1, 0, 0, 0, 0 } +}; + +static const Bit32u pg_lfo_sh2[8][8] = { + { 7, 7, 7, 7, 7, 7, 7, 7 }, + { 7, 7, 7, 7, 2, 2, 2, 2 }, + { 7, 7, 7, 2, 2, 2, 7, 7 }, + { 7, 7, 2, 2, 7, 7, 2, 2 }, + { 7, 7, 2, 7, 7, 7, 2, 7 }, + { 7, 7, 7, 2, 7, 7, 2, 1 }, + { 7, 7, 7, 2, 7, 7, 2, 1 }, + { 7, 7, 7, 2, 7, 7, 2, 1 } +}; + +/* Address decoder */ +static const Bit32u op_offset[12] = { + 0x000, /* Ch1 OP1/OP2 */ + 0x001, /* Ch2 OP1/OP2 */ + 0x002, /* Ch3 OP1/OP2 */ + 0x100, /* Ch4 OP1/OP2 */ + 0x101, /* Ch5 OP1/OP2 */ + 0x102, /* Ch6 OP1/OP2 */ + 0x004, /* Ch1 OP3/OP4 */ + 0x005, /* Ch2 OP3/OP4 */ + 0x006, /* Ch3 OP3/OP4 */ + 0x104, /* Ch4 OP3/OP4 */ + 0x105, /* Ch5 OP3/OP4 */ + 0x106 /* Ch6 OP3/OP4 */ +}; + +static const Bit32u ch_offset[6] = { + 0x000, /* Ch1 */ + 0x001, /* Ch2 */ + 0x002, /* Ch3 */ + 0x100, /* Ch4 */ + 0x101, /* Ch5 */ + 0x102 /* Ch6 */ +}; + +/* LFO */ +static const Bit32u lfo_cycles[8] = { + 108, 77, 71, 67, 62, 44, 8, 5 +}; + +/* FM algorithm */ +static const Bit32u fm_algorithm[4][6][8] = { + { + { 1, 1, 1, 1, 1, 1, 1, 1 }, /* OP1_0 */ + { 1, 1, 1, 1, 1, 1, 1, 1 }, /* OP1_1 */ + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP2 */ + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */ + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */ + { 0, 0, 0, 0, 0, 0, 0, 1 } /* Out */ + }, + { + { 0, 1, 0, 0, 0, 1, 0, 0 }, /* OP1_0 */ + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_1 */ + { 1, 1, 1, 0, 0, 0, 0, 0 }, /* OP2 */ + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */ + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */ + { 0, 0, 0, 0, 0, 1, 1, 1 } /* Out */ + }, + { + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_0 */ + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_1 */ + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP2 */ + { 1, 0, 0, 1, 1, 1, 1, 0 }, /* Last operator */ + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */ + { 0, 0, 0, 0, 1, 1, 1, 1 } /* Out */ + }, + { + { 0, 0, 1, 0, 0, 1, 0, 0 }, /* OP1_0 */ + { 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_1 */ + { 0, 0, 0, 1, 0, 0, 0, 0 }, /* OP2 */ + { 1, 1, 0, 1, 1, 0, 0, 0 }, /* Last operator */ + { 0, 0, 1, 0, 0, 0, 0, 0 }, /* Last operator */ + { 1, 1, 1, 1, 1, 1, 1, 1 } /* Out */ + } +}; + +static Bit32u chip_type = ym3438_type_discrete; + +void OPN2_DoIO(ym3438_t *chip) +{ + /* Write signal check */ + chip->write_a_en = (chip->write_a & 0x03) == 0x01; + chip->write_d_en = (chip->write_d & 0x03) == 0x01; + chip->write_a <<= 1; + chip->write_d <<= 1; + /* Busy counter */ + chip->busy = chip->write_busy; + chip->write_busy_cnt += chip->write_busy; + chip->write_busy = (chip->write_busy && !(chip->write_busy_cnt >> 5)) || chip->write_d_en; + chip->write_busy_cnt &= 0x1f; +} + +void OPN2_DoRegWrite(ym3438_t *chip) +{ + Bit32u i; + Bit32u slot = chip->cycles % 12; + Bit32u address; + Bit32u channel = chip->channel; + /* Update registers */ + if (chip->write_fm_data) + { + /* Slot */ + if (op_offset[slot] == (chip->address & 0x107)) + { + if (chip->address & 0x08) + { + /* OP2, OP4 */ + slot += 12; + } + address = chip->address & 0xf0; + switch (address) + { + case 0x30: /* DT, MULTI */ + chip->multi[slot] = chip->data & 0x0f; + if (!chip->multi[slot]) + { + chip->multi[slot] = 1; + } + else + { + chip->multi[slot] <<= 1; + } + chip->dt[slot] = (chip->data >> 4) & 0x07; + break; + case 0x40: /* TL */ + chip->tl[slot] = chip->data & 0x7f; + break; + case 0x50: /* KS, AR */ + chip->ar[slot] = chip->data & 0x1f; + chip->ks[slot] = (chip->data >> 6) & 0x03; + break; + case 0x60: /* AM, DR */ + chip->dr[slot] = chip->data & 0x1f; + chip->am[slot] = (chip->data >> 7) & 0x01; + break; + case 0x70: /* SR */ + chip->sr[slot] = chip->data & 0x1f; + break; + case 0x80: /* SL, RR */ + chip->rr[slot] = chip->data & 0x0f; + chip->sl[slot] = (chip->data >> 4) & 0x0f; + chip->sl[slot] |= (chip->sl[slot] + 1) & 0x10; + break; + case 0x90: /* SSG-EG */ + chip->ssg_eg[slot] = chip->data & 0x0f; + break; + default: + break; + } + } + + /* Channel */ + if (ch_offset[channel] == (chip->address & 0x103)) + { + address = chip->address & 0xfc; + switch (address) + { + case 0xa0: + chip->fnum[channel] = (chip->data & 0xff) | ((chip->reg_a4 & 0x07) << 8); + chip->block[channel] = (chip->reg_a4 >> 3) & 0x07; + chip->kcode[channel] = (chip->block[channel] << 2) | fn_note[chip->fnum[channel] >> 7]; + break; + case 0xa4: + chip->reg_a4 = chip->data & 0xff; + break; + case 0xa8: + chip->fnum_3ch[channel] = (chip->data & 0xff) | ((chip->reg_ac & 0x07) << 8); + chip->block_3ch[channel] = (chip->reg_ac >> 3) & 0x07; + chip->kcode_3ch[channel] = (chip->block_3ch[channel] << 2) | fn_note[chip->fnum_3ch[channel] >> 7]; + break; + case 0xac: + chip->reg_ac = chip->data & 0xff; + break; + case 0xb0: + chip->connect[channel] = chip->data & 0x07; + chip->fb[channel] = (chip->data >> 3) & 0x07; + break; + case 0xb4: + chip->pms[channel] = chip->data & 0x07; + chip->ams[channel] = (chip->data >> 4) & 0x03; + chip->pan_l[channel] = (chip->data >> 7) & 0x01; + chip->pan_r[channel] = (chip->data >> 6) & 0x01; + break; + default: + break; + } + } + } + + if (chip->write_a_en || chip->write_d_en) + { + /* Data */ + if (chip->write_a_en) + { + chip->write_fm_data = 0; + } + + if (chip->write_fm_address && chip->write_d_en) + { + chip->write_fm_data = 1; + } + + /* Address */ + if (chip->write_a_en) + { + if ((chip->write_data & 0xf0) != 0x00) + { + /* FM Write */ + chip->address = chip->write_data; + chip->write_fm_address = 1; + } + else + { + /* SSG write */ + chip->write_fm_address = 0; + } + } + + /* FM Mode */ + /* Data */ + if (chip->write_d_en && (chip->write_data & 0x100) == 0) + { + switch (chip->address) + { + case 0x21: /* LSI test 1 */ + for (i = 0; i < 8; i++) + { + chip->mode_test_21[i] = (chip->write_data >> i) & 0x01; + } + break; + case 0x22: /* LFO control */ + if ((chip->write_data >> 3) & 0x01) + { + chip->lfo_en = 0x7f; + } + else + { + chip->lfo_en = 0; + } + chip->lfo_freq = chip->write_data & 0x07; + break; + case 0x24: /* Timer A */ + chip->timer_a_reg &= 0x03; + chip->timer_a_reg |= (chip->write_data & 0xff) << 2; + break; + case 0x25: + chip->timer_a_reg &= 0x3fc; + chip->timer_a_reg |= chip->write_data & 0x03; + break; + case 0x26: /* Timer B */ + chip->timer_b_reg = chip->write_data & 0xff; + break; + case 0x27: /* CSM, Timer control */ + chip->mode_ch3 = (chip->write_data & 0xc0) >> 6; + chip->mode_csm = chip->mode_ch3 == 2; + chip->timer_a_load = chip->write_data & 0x01; + chip->timer_a_enable = (chip->write_data >> 2) & 0x01; + chip->timer_a_reset = (chip->write_data >> 4) & 0x01; + chip->timer_b_load = (chip->write_data >> 1) & 0x01; + chip->timer_b_enable = (chip->write_data >> 3) & 0x01; + chip->timer_b_reset = (chip->write_data >> 5) & 0x01; + break; + case 0x28: /* Key on/off */ + for (i = 0; i < 4; i++) + { + chip->mode_kon_operator[i] = (chip->write_data >> (4 + i)) & 0x01; + } + if ((chip->write_data & 0x03) == 0x03) + { + /* Invalid address */ + chip->mode_kon_channel = 0xff; + } + else + { + chip->mode_kon_channel = (chip->write_data & 0x03) + ((chip->write_data >> 2) & 1) * 3; + } + break; + case 0x2a: /* DAC data */ + chip->dacdata &= 0x01; + chip->dacdata |= (chip->write_data ^ 0x80) << 1; + break; + case 0x2b: /* DAC enable */ + chip->dacen = chip->write_data >> 7; + break; + case 0x2c: /* LSI test 2 */ + for (i = 0; i < 8; i++) + { + chip->mode_test_2c[i] = (chip->write_data >> i) & 0x01; + } + chip->dacdata &= 0x1fe; + chip->dacdata |= chip->mode_test_2c[3]; + chip->eg_custom_timer = !chip->mode_test_2c[7] && chip->mode_test_2c[6]; + break; + default: + break; + } + } + + /* Address */ + if (chip->write_a_en) + { + chip->write_fm_mode_a = chip->write_data & 0xff; + } + } + + if (chip->write_fm_data) + { + chip->data = chip->write_data & 0xff; + } +} + +void OPN2_PhaseCalcIncrement(ym3438_t *chip) +{ + Bit32u chan = chip->channel; + Bit32u slot = chip->cycles; + Bit32u fnum = chip->pg_fnum; + Bit32u fnum_h = fnum >> 4; + Bit32u fm; + Bit32u basefreq; + Bit8u lfo = chip->lfo_pm; + Bit8u lfo_l = lfo & 0x0f; + Bit8u pms = chip->pms[chan]; + Bit8u dt = chip->dt[slot]; + Bit8u dt_l = dt & 0x03; + Bit8u detune = 0; + Bit8u block, note; + Bit8u sum, sum_h, sum_l; + Bit8u kcode = chip->pg_kcode; + + fnum <<= 1; + /* Apply LFO */ + if (lfo_l & 0x08) + { + lfo_l ^= 0x0f; + } + fm = (fnum_h >> pg_lfo_sh1[pms][lfo_l]) + (fnum_h >> pg_lfo_sh2[pms][lfo_l]); + if (pms > 5) + { + fm <<= pms - 5; + } + fm >>= 2; + if (lfo & 0x10) + { + fnum -= fm; + } + else + { + fnum += fm; + } + fnum &= 0xfff; + + basefreq = (fnum << chip->pg_block) >> 2; + + /* Apply detune */ + if (dt_l) + { + if (kcode > 0x1c) + { + kcode = 0x1c; + } + block = kcode >> 2; + note = kcode & 0x03; + sum = block + 9 + ((dt_l == 3) | (dt_l & 0x02)); + sum_h = sum >> 1; + sum_l = sum & 0x01; + detune = pg_detune[(sum_l << 2) | note] >> (9 - sum_h); + } + if (dt & 0x04) + { + basefreq -= detune; + } + else + { + basefreq += detune; + } + basefreq &= 0x1ffff; + chip->pg_inc[slot] = (basefreq * chip->multi[slot]) >> 1; + chip->pg_inc[slot] &= 0xfffff; +} + +void OPN2_PhaseGenerate(ym3438_t *chip) +{ + Bit32u slot; + /* Mask increment */ + slot = (chip->cycles + 20) % 24; + if (chip->pg_reset[slot]) + { + chip->pg_inc[slot] = 0; + } + /* Phase step */ + slot = (chip->cycles + 19) % 24; + chip->pg_phase[slot] += chip->pg_inc[slot]; + chip->pg_phase[slot] &= 0xfffff; + if (chip->pg_reset[slot] || chip->mode_test_21[3]) + { + chip->pg_phase[slot] = 0; + } +} + +void OPN2_EnvelopeSSGEG(ym3438_t *chip) +{ + Bit32u slot = chip->cycles; + Bit8u direction = 0; + chip->eg_ssg_pgrst_latch[slot] = 0; + chip->eg_ssg_repeat_latch[slot] = 0; + chip->eg_ssg_hold_up_latch[slot] = 0; + chip->eg_ssg_inv[slot] = 0; + if (chip->ssg_eg[slot] & 0x08) + { + direction = chip->eg_ssg_dir[slot]; + if (chip->eg_level[slot] & 0x200) + { + /* Reset */ + if ((chip->ssg_eg[slot] & 0x03) == 0x00) + { + chip->eg_ssg_pgrst_latch[slot] = 1; + } + /* Repeat */ + if ((chip->ssg_eg[slot] & 0x01) == 0x00) + { + chip->eg_ssg_repeat_latch[slot] = 1; + } + /* Inverse */ + if ((chip->ssg_eg[slot] & 0x03) == 0x02) + { + direction ^= 1; + } + if ((chip->ssg_eg[slot] & 0x03) == 0x03) + { + direction = 1; + } + } + /* Hold up */ + if (chip->eg_kon_latch[slot] + && ((chip->ssg_eg[slot] & 0x07) == 0x05 || (chip->ssg_eg[slot] & 0x07) == 0x03)) + { + chip->eg_ssg_hold_up_latch[slot] = 1; + } + direction &= chip->eg_kon[slot]; + chip->eg_ssg_inv[slot] = (chip->eg_ssg_dir[slot] ^ ((chip->ssg_eg[slot] >> 2) & 0x01)) + & chip->eg_kon[slot]; + } + chip->eg_ssg_dir[slot] = direction; + chip->eg_ssg_enable[slot] = (chip->ssg_eg[slot] >> 3) & 0x01; +} + +void OPN2_EnvelopeADSR(ym3438_t *chip) +{ + Bit32u slot = (chip->cycles + 22) % 24; + + Bit8u nkon = chip->eg_kon_latch[slot]; + Bit8u okon = chip->eg_kon[slot]; + Bit8u kon_event; + Bit8u koff_event; + Bit8u eg_off; + Bit16s level; + Bit16s nextlevel = 0; + Bit16s ssg_level; + Bit8u nextstate = chip->eg_state[slot]; + Bit16s inc = 0; + chip->eg_read[0] = chip->eg_read_inc; + chip->eg_read_inc = chip->eg_inc > 0; + + /* Reset phase generator */ + chip->pg_reset[slot] = (nkon && !okon) || chip->eg_ssg_pgrst_latch[slot]; + + /* KeyOn/Off */ + kon_event = (nkon && !okon) || (okon && chip->eg_ssg_repeat_latch[slot]); + koff_event = okon && !nkon; + + ssg_level = level = (Bit16s)chip->eg_level[slot]; + + if (chip->eg_ssg_inv[slot]) + { + /* Inverse */ + ssg_level = 512 - level; + ssg_level &= 0x3ff; + } + if (koff_event) + { + level = ssg_level; + } + if (chip->eg_ssg_enable[slot]) + { + eg_off = level >> 9; + } + else + { + eg_off = (level & 0x3f0) == 0x3f0; + } + nextlevel = level; + if (kon_event) + { + nextstate = eg_num_attack; + /* Instant attack */ + if (chip->eg_ratemax) + { + nextlevel = 0; + } + else if (chip->eg_state[slot] == eg_num_attack && level != 0 && chip->eg_inc && nkon) + { + inc = (~level << chip->eg_inc) >> 5; + } + } + else + { + switch (chip->eg_state[slot]) + { + case eg_num_attack: + if (level == 0) + { + nextstate = eg_num_decay; + } + else if(chip->eg_inc && !chip->eg_ratemax && nkon) + { + inc = (~level << chip->eg_inc) >> 5; + } + break; + case eg_num_decay: + if ((level >> 5) == chip->eg_sl[1]) + { + nextstate = eg_num_sustain; + } + else if (!eg_off && chip->eg_inc) + { + inc = 1 << (chip->eg_inc - 1); + if (chip->eg_ssg_enable[slot]) + { + inc <<= 2; + } + } + break; + case eg_num_sustain: + case eg_num_release: + if (!eg_off && chip->eg_inc) + { + inc = 1 << (chip->eg_inc - 1); + if (chip->eg_ssg_enable[slot]) + { + inc <<= 2; + } + } + break; + default: + break; + } + if (!nkon) + { + nextstate = eg_num_release; + } + } + if (chip->eg_kon_csm[slot]) + { + nextlevel |= chip->eg_tl[1] << 3; + } + + /* Envelope off */ + if (!kon_event && !chip->eg_ssg_hold_up_latch[slot] && chip->eg_state[slot] != eg_num_attack && eg_off) + { + nextstate = eg_num_release; + nextlevel = 0x3ff; + } + + nextlevel += inc; + + chip->eg_kon[slot] = chip->eg_kon_latch[slot]; + chip->eg_level[slot] = (Bit16u)nextlevel & 0x3ff; + chip->eg_state[slot] = nextstate; +} + +void OPN2_EnvelopePrepare(ym3438_t *chip) +{ + Bit8u rate; + Bit8u sum; + Bit8u inc = 0; + Bit32u slot = chip->cycles; + Bit8u rate_sel; + + /* Prepare increment */ + rate = (chip->eg_rate << 1) + chip->eg_ksv; + + if (rate > 0x3f) + { + rate = 0x3f; + } + + sum = ((rate >> 2) + chip->eg_shift_lock) & 0x0f; + if (chip->eg_rate != 0 && chip->eg_quotient == 2) + { + if (rate < 48) + { + switch (sum) + { + case 12: + inc = 1; + break; + case 13: + inc = (rate >> 1) & 0x01; + break; + case 14: + inc = rate & 0x01; + break; + default: + break; + } + } + else + { + inc = eg_stephi[rate & 0x03][chip->eg_timer_low_lock] + (rate >> 2) - 11; + if (inc > 4) + { + inc = 4; + } + } + } + chip->eg_inc = inc; + chip->eg_ratemax = (rate >> 1) == 0x1f; + + /* Prepare rate & ksv */ + rate_sel = chip->eg_state[slot]; + if ((chip->eg_kon[slot] && chip->eg_ssg_repeat_latch[slot]) + || (!chip->eg_kon[slot] && chip->eg_kon_latch[slot])) + { + rate_sel = eg_num_attack; + } + switch (rate_sel) + { + case eg_num_attack: + chip->eg_rate = chip->ar[slot]; + break; + case eg_num_decay: + chip->eg_rate = chip->dr[slot]; + break; + case eg_num_sustain: + chip->eg_rate = chip->sr[slot]; + break; + case eg_num_release: + chip->eg_rate = (chip->rr[slot] << 1) | 0x01; + break; + default: + break; + } + chip->eg_ksv = chip->pg_kcode >> (chip->ks[slot] ^ 0x03); + if (chip->am[slot]) + { + chip->eg_lfo_am = chip->lfo_am >> eg_am_shift[chip->ams[chip->channel]]; + } + else + { + chip->eg_lfo_am = 0; + } + /* Delay TL & SL value */ + chip->eg_tl[1] = chip->eg_tl[0]; + chip->eg_tl[0] = chip->tl[slot]; + chip->eg_sl[1] = chip->eg_sl[0]; + chip->eg_sl[0] = chip->sl[slot]; +} + +void OPN2_EnvelopeGenerate(ym3438_t *chip) +{ + Bit32u slot = (chip->cycles + 23) % 24; + Bit16u level; + + level = chip->eg_level[slot]; + + if (chip->eg_ssg_inv[slot]) + { + /* Inverse */ + level = 512 - level; + } + if (chip->mode_test_21[5]) + { + level = 0; + } + level &= 0x3ff; + + /* Apply AM LFO */ + level += chip->eg_lfo_am; + + /* Apply TL */ + if (!(chip->mode_csm && chip->channel == 2 + 1)) + { + level += chip->eg_tl[0] << 3; + } + if (level > 0x3ff) + { + level = 0x3ff; + } + chip->eg_out[slot] = level; +} + +void OPN2_UpdateLFO(ym3438_t *chip) +{ + if ((chip->lfo_quotient & lfo_cycles[chip->lfo_freq]) == lfo_cycles[chip->lfo_freq]) + { + chip->lfo_quotient = 0; + chip->lfo_cnt++; + } + else + { + chip->lfo_quotient += chip->lfo_inc; + } + chip->lfo_cnt &= chip->lfo_en; +} + +void OPN2_FMPrepare(ym3438_t *chip) +{ + Bit32u slot = (chip->cycles + 6) % 24; + Bit32u channel = chip->channel; + Bit16s mod, mod1, mod2; + Bit32u op = slot / 6; + Bit8u connect = chip->connect[channel]; + Bit32u prevslot = (chip->cycles + 18) % 24; + + /* Calculate modulation */ + mod1 = mod2 = 0; + + if (fm_algorithm[op][0][connect]) + { + mod2 |= chip->fm_op1[channel][0]; + } + if (fm_algorithm[op][1][connect]) + { + mod1 |= chip->fm_op1[channel][1]; + } + if (fm_algorithm[op][2][connect]) + { + mod1 |= chip->fm_op2[channel]; + } + if (fm_algorithm[op][3][connect]) + { + mod2 |= chip->fm_out[prevslot]; + } + if (fm_algorithm[op][4][connect]) + { + mod1 |= chip->fm_out[prevslot]; + } + mod = mod1 + mod2; + if (op == 0) + { + /* Feedback */ + mod = mod >> (10 - chip->fb[channel]); + if (!chip->fb[channel]) + { + mod = 0; + } + } + else + { + mod >>= 1; + } + chip->fm_mod[slot] = mod; + + slot = (chip->cycles + 18) % 24; + /* OP1 */ + if (slot / 6 == 0) + { + chip->fm_op1[channel][1] = chip->fm_op1[channel][0]; + chip->fm_op1[channel][0] = chip->fm_out[slot]; + } + /* OP2 */ + if (slot / 6 == 2) + { + chip->fm_op2[channel] = chip->fm_out[slot]; + } +} + +void OPN2_ChGenerate(ym3438_t *chip) +{ + Bit32u slot = (chip->cycles + 18) % 24; + Bit32u channel = chip->channel; + Bit32u op = slot / 6; + Bit32u test_dac = chip->mode_test_2c[5]; + Bit16s acc = chip->ch_acc[channel]; + Bit16s add = test_dac; + Bit16s sum = 0; + if (op == 0 && !test_dac) + { + acc = 0; + } + if (fm_algorithm[op][5][chip->connect[channel]] && !test_dac) + { + add += chip->fm_out[slot] >> 5; + } + sum = acc + add; + /* Clamp */ + if (sum > 255) + { + sum = 255; + } + else if(sum < -256) + { + sum = -256; + } + + if (op == 0 || test_dac) + { + chip->ch_out[channel] = chip->ch_acc[channel]; + } + chip->ch_acc[channel] = sum; +} + +void OPN2_ChOutput(ym3438_t *chip) +{ + Bit32u cycles = chip->cycles; + Bit32u slot = chip->cycles; + Bit32u channel = chip->channel; + Bit32u test_dac = chip->mode_test_2c[5]; + Bit16s out; + Bit16s sign; + Bit32u out_en; + chip->ch_read = chip->ch_lock; + if (slot < 12) + { + /* Ch 4,5,6 */ + channel++; + } + if ((cycles & 3) == 0) + { + if (!test_dac) + { + /* Lock value */ + chip->ch_lock = chip->ch_out[channel]; + } + chip->ch_lock_l = chip->pan_l[channel]; + chip->ch_lock_r = chip->pan_r[channel]; + } + /* Ch 6 */ + if (((cycles >> 2) == 1 && chip->dacen) || test_dac) + { + out = (Bit16s)chip->dacdata; + out <<= 7; + out >>= 7; + } + else + { + out = chip->ch_lock; + } + chip->mol = 0; + chip->mor = 0; + + if (chip_type == ym3438_type_ym2612) + { + out_en = ((cycles & 3) == 3) || test_dac; + /* YM2612 DAC emulation(not verified) */ + sign = out >> 8; + if (out >= 0) + { + out++; + sign++; + } + if (chip->ch_lock_l && out_en) + { + chip->mol = out; + } + else + { + chip->mol = sign; + } + if (chip->ch_lock_r && out_en) + { + chip->mor = out; + } + else + { + chip->mor = sign; + } + /* Amplify signal */ + chip->mol *= 3; + chip->mor *= 3; + } + else + { + out_en = ((cycles & 3) != 0) || test_dac; + /* Discrete YM3438 seems has the ladder effect too */ + if (out >= 0 && chip_type == ym3438_type_discrete) + { + out++; + } + if (chip->ch_lock_l && out_en) + { + chip->mol = out; + } + if (chip->ch_lock_r && out_en) + { + chip->mor = out; + } + } +} + +void OPN2_FMGenerate(ym3438_t *chip) +{ + Bit32u slot = (chip->cycles + 19) % 24; + /* Calculate phase */ + Bit16u phase = (chip->fm_mod[slot] + (chip->pg_phase[slot] >> 10)) & 0x3ff; + Bit16u quarter; + Bit16u level; + Bit16s output; + if (phase & 0x100) + { + quarter = (phase ^ 0xff) & 0xff; + } + else + { + quarter = phase & 0xff; + } + level = logsinrom[quarter]; + /* Apply envelope */ + level += chip->eg_out[slot] << 2; + /* Transform */ + if (level > 0x1fff) + { + level = 0x1fff; + } + output = ((exprom[(level & 0xff) ^ 0xff] | 0x400) << 2) >> (level >> 8); + if (phase & 0x200) + { + output = ((~output) ^ (chip->mode_test_21[4] << 13)) + 1; + } + else + { + output = output ^ (chip->mode_test_21[4] << 13); + } + output <<= 2; + output >>= 2; + chip->fm_out[slot] = output; +} + +void OPN2_DoTimerA(ym3438_t *chip) +{ + Bit16u time; + Bit8u load; + load = chip->timer_a_overflow; + if (chip->cycles == 2) + { + /* Lock load value */ + load |= (!chip->timer_a_load_lock && chip->timer_a_load); + chip->timer_a_load_lock = chip->timer_a_load; + if (chip->mode_csm) + { + /* CSM KeyOn */ + chip->mode_kon_csm = load; + } + else + { + chip->mode_kon_csm = 0; + } + } + /* Load counter */ + if (chip->timer_a_load_latch) + { + time = chip->timer_a_reg; + } + else + { + time = chip->timer_a_cnt; + } + chip->timer_a_load_latch = load; + /* Increase counter */ + if ((chip->cycles == 1 && chip->timer_a_load_lock) || chip->mode_test_21[2]) + { + time++; + } + /* Set overflow flag */ + if (chip->timer_a_reset) + { + chip->timer_a_reset = 0; + chip->timer_a_overflow_flag = 0; + } + else + { + chip->timer_a_overflow_flag |= chip->timer_a_overflow & chip->timer_a_enable; + } + chip->timer_a_overflow = (time >> 10); + chip->timer_a_cnt = time & 0x3ff; +} + +void OPN2_DoTimerB(ym3438_t *chip) +{ + Bit16u time; + Bit8u load; + load = chip->timer_b_overflow; + if (chip->cycles == 2) + { + /* Lock load value */ + load |= (!chip->timer_b_load_lock && chip->timer_b_load); + chip->timer_b_load_lock = chip->timer_b_load; + } + /* Load counter */ + if (chip->timer_b_load_latch) + { + time = chip->timer_b_reg; + } + else + { + time = chip->timer_b_cnt; + } + chip->timer_b_load_latch = load; + /* Increase counter */ + if (chip->cycles == 1) + { + chip->timer_b_subcnt++; + } + if ((chip->timer_b_subcnt == 0x10 && chip->timer_b_load_lock) || chip->mode_test_21[2]) + { + time++; + } + chip->timer_b_subcnt &= 0x0f; + /* Set overflow flag */ + if (chip->timer_b_reset) + { + chip->timer_b_reset = 0; + chip->timer_b_overflow_flag = 0; + } + else + { + chip->timer_b_overflow_flag |= chip->timer_b_overflow & chip->timer_b_enable; + } + chip->timer_b_overflow = (time >> 8); + chip->timer_b_cnt = time & 0xff; +} + +void OPN2_KeyOn(ym3438_t*chip) +{ + Bit32u slot = chip->cycles; + Bit32u chan = chip->channel; + /* Key On */ + chip->eg_kon_latch[slot] = chip->mode_kon[slot]; + chip->eg_kon_csm[slot] = 0; + if (chip->channel == 2 && chip->mode_kon_csm) + { + /* CSM Key On */ + chip->eg_kon_latch[slot] = 1; + chip->eg_kon_csm[slot] = 1; + } + if (chip->cycles == chip->mode_kon_channel) + { + /* OP1 */ + chip->mode_kon[chan] = chip->mode_kon_operator[0]; + /* OP2 */ + chip->mode_kon[chan + 12] = chip->mode_kon_operator[1]; + /* OP3 */ + chip->mode_kon[chan + 6] = chip->mode_kon_operator[2]; + /* OP4 */ + chip->mode_kon[chan + 18] = chip->mode_kon_operator[3]; + } +} + +void OPN2_Reset(ym3438_t *chip, Bit32u rate, Bit32u clock) +{ + Bit32u i, rateratio; + rateratio = (Bit32u)chip->rateratio; + memset(chip, 0, sizeof(ym3438_t)); + for (i = 0; i < 24; i++) + { + chip->eg_out[i] = 0x3ff; + chip->eg_level[i] = 0x3ff; + chip->eg_state[i] = eg_num_release; + chip->multi[i] = 1; + } + for (i = 0; i < 6; i++) + { + chip->pan_l[i] = 1; + chip->pan_r[i] = 1; + } + + if (rate != 0) + { + chip->rateratio = (Bit32s)(Bit32u)((((Bit64u)144 * rate) << RSM_FRAC) / clock); + } + else + { + chip->rateratio = (Bit32s)rateratio; + } +} + +void OPN2_SetChipType(Bit32u type) +{ + chip_type = type; +} + +void OPN2_Clock(ym3438_t *chip, Bit16s *buffer) +{ + Bit32u slot = chip->cycles; + chip->lfo_inc = chip->mode_test_21[1]; + chip->pg_read >>= 1; + chip->eg_read[1] >>= 1; + chip->eg_cycle++; + /* Lock envelope generator timer value */ + if (chip->cycles == 1 && chip->eg_quotient == 2) + { + if (chip->eg_cycle_stop) + { + chip->eg_shift_lock = 0; + } + else + { + chip->eg_shift_lock = chip->eg_shift + 1; + } + chip->eg_timer_low_lock = chip->eg_timer & 0x03; + } + /* Cycle specific functions */ + switch (chip->cycles) + { + case 0: + chip->lfo_pm = chip->lfo_cnt >> 2; + if (chip->lfo_cnt & 0x40) + { + chip->lfo_am = chip->lfo_cnt & 0x3f; + } + else + { + chip->lfo_am = chip->lfo_cnt ^ 0x3f; + } + chip->lfo_am <<= 1; + break; + case 1: + chip->eg_quotient++; + chip->eg_quotient %= 3; + chip->eg_cycle = 0; + chip->eg_cycle_stop = 1; + chip->eg_shift = 0; + chip->eg_timer_inc |= chip->eg_quotient >> 1; + chip->eg_timer = chip->eg_timer + chip->eg_timer_inc; + chip->eg_timer_inc = chip->eg_timer >> 12; + chip->eg_timer &= 0xfff; + break; + case 2: + chip->pg_read = chip->pg_phase[21] & 0x3ff; + chip->eg_read[1] = chip->eg_out[0]; + break; + case 13: + chip->eg_cycle = 0; + chip->eg_cycle_stop = 1; + chip->eg_shift = 0; + chip->eg_timer = chip->eg_timer + chip->eg_timer_inc; + chip->eg_timer_inc = chip->eg_timer >> 12; + chip->eg_timer &= 0xfff; + break; + case 23: + chip->lfo_inc |= 1; + break; + } + chip->eg_timer &= ~(chip->mode_test_21[5] << chip->eg_cycle); + if (((chip->eg_timer >> chip->eg_cycle) | (chip->pin_test_in & chip->eg_custom_timer)) & chip->eg_cycle_stop) + { + chip->eg_shift = chip->eg_cycle; + chip->eg_cycle_stop = 0; + } + + OPN2_DoIO(chip); + + OPN2_DoTimerA(chip); + OPN2_DoTimerB(chip); + OPN2_KeyOn(chip); + + OPN2_ChOutput(chip); + OPN2_ChGenerate(chip); + + OPN2_FMPrepare(chip); + OPN2_FMGenerate(chip); + + OPN2_PhaseGenerate(chip); + OPN2_PhaseCalcIncrement(chip); + + OPN2_EnvelopeADSR(chip); + OPN2_EnvelopeGenerate(chip); + OPN2_EnvelopeSSGEG(chip); + OPN2_EnvelopePrepare(chip); + + /* Prepare fnum & block */ + if (chip->mode_ch3) + { + /* Channel 3 special mode */ + switch (slot) + { + case 1: /* OP1 */ + chip->pg_fnum = chip->fnum_3ch[1]; + chip->pg_block = chip->block_3ch[1]; + chip->pg_kcode = chip->kcode_3ch[1]; + break; + case 7: /* OP3 */ + chip->pg_fnum = chip->fnum_3ch[0]; + chip->pg_block = chip->block_3ch[0]; + chip->pg_kcode = chip->kcode_3ch[0]; + break; + case 13: /* OP2 */ + chip->pg_fnum = chip->fnum_3ch[2]; + chip->pg_block = chip->block_3ch[2]; + chip->pg_kcode = chip->kcode_3ch[2]; + break; + case 19: /* OP4 */ + default: + chip->pg_fnum = chip->fnum[(chip->channel + 1) % 6]; + chip->pg_block = chip->block[(chip->channel + 1) % 6]; + chip->pg_kcode = chip->kcode[(chip->channel + 1) % 6]; + break; + } + } + else + { + chip->pg_fnum = chip->fnum[(chip->channel + 1) % 6]; + chip->pg_block = chip->block[(chip->channel + 1) % 6]; + chip->pg_kcode = chip->kcode[(chip->channel + 1) % 6]; + } + + OPN2_UpdateLFO(chip); + OPN2_DoRegWrite(chip); + chip->cycles = (chip->cycles + 1) % 24; + chip->channel = chip->cycles % 6; + + buffer[0] = chip->mol; + buffer[1] = chip->mor; +} + +void OPN2_Write(ym3438_t *chip, Bit32u port, Bit8u data) +{ + port &= 3; + chip->write_data = ((port << 7) & 0x100) | data; + if (port & 1) + { + /* Data */ + chip->write_d |= 1; + } + else + { + /* Address */ + chip->write_a |= 1; + } +} + +void OPN2_SetTestPin(ym3438_t *chip, Bit32u value) +{ + chip->pin_test_in = value & 1; +} + +Bit32u OPN2_ReadTestPin(ym3438_t *chip) +{ + if (!chip->mode_test_2c[7]) + { + return 0; + } + return chip->cycles == 23; +} + +Bit32u OPN2_ReadIRQPin(ym3438_t *chip) +{ + return chip->timer_a_overflow_flag | chip->timer_b_overflow_flag; +} + +Bit8u OPN2_Read(ym3438_t *chip, Bit32u port) +{ + if ((port & 3) == 0 || chip_type == ym3438_type_asic) + { + if (chip->mode_test_21[6]) + { + /* Read test data */ + Bit32u slot = (chip->cycles + 18) % 24; + Bit16u testdata = ((chip->pg_read & 0x01) << 15) + | ((chip->eg_read[chip->mode_test_21[0]] & 0x01) << 14); + if (chip->mode_test_2c[4]) + { + testdata |= chip->ch_read & 0x1ff; + } + else + { + testdata |= chip->fm_out[slot] & 0x3fff; + } + if (chip->mode_test_21[7]) + { + return testdata & 0xff; + } + else + { + return testdata >> 8; + } + } + else + { + return (Bit8u)(chip->busy << 7) | (Bit8u)(chip->timer_b_overflow_flag << 1) + | (Bit8u)chip->timer_a_overflow_flag; + } + } + return 0; +} + +void OPN2_WriteBuffered(ym3438_t *chip, Bit32u port, Bit8u data) +{ + Bit64u time1, time2; + Bit16s buffer[2]; + Bit64u skip; + + if (chip->writebuf[chip->writebuf_last].port & 0x04) + { + OPN2_Write(chip, chip->writebuf[chip->writebuf_last].port & 0X03, + chip->writebuf[chip->writebuf_last].data); + + chip->writebuf_cur = (chip->writebuf_last + 1) % OPN_WRITEBUF_SIZE; + skip = chip->writebuf[chip->writebuf_last].time - chip->writebuf_samplecnt; + chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time; + while (skip--) + { + OPN2_Clock(chip, buffer); + } + } + + chip->writebuf[chip->writebuf_last].port = (port & 0x03) | 0x04; + chip->writebuf[chip->writebuf_last].data = data; + time1 = chip->writebuf_lasttime + OPN_WRITEBUF_DELAY; + time2 = chip->writebuf_samplecnt; + + if (time1 < time2) + { + time1 = time2; + } + + chip->writebuf[chip->writebuf_last].time = time1; + chip->writebuf_lasttime = time1; + chip->writebuf_last = (chip->writebuf_last + 1) % OPN_WRITEBUF_SIZE; +} + +void OPN2_Generate(ym3438_t *chip, Bit16s *buf) +{ + Bit32u i; + Bit16s buffer[2]; + Bit32u mute; + + buf[0] = 0; + buf[1] = 0; + + for (i = 0; i < 24; i++) + { + switch (chip->cycles >> 2) + { + case 0: /* Ch 2 */ + mute = chip->mute[1]; + break; + case 1: /* Ch 6, DAC */ + mute = chip->mute[5 + chip->dacen]; + break; + case 2: /* Ch 4 */ + mute = chip->mute[3]; + break; + case 3: /* Ch 1 */ + mute = chip->mute[0]; + break; + case 4: /* Ch 5 */ + mute = chip->mute[4]; + break; + case 5: /* Ch 3 */ + mute = chip->mute[2]; + break; + default: + mute = 0; + break; + } + OPN2_Clock(chip, buffer); + if (!mute) + { + buf[0] += buffer[0]; + buf[1] += buffer[1]; + } + + while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt) + { + if (!(chip->writebuf[chip->writebuf_cur].port & 0x04)) + { + break; + } + chip->writebuf[chip->writebuf_cur].port &= 0x03; + OPN2_Write(chip, chip->writebuf[chip->writebuf_cur].port, + chip->writebuf[chip->writebuf_cur].data); + chip->writebuf_cur = (chip->writebuf_cur + 1) % OPN_WRITEBUF_SIZE; + } + chip->writebuf_samplecnt++; + } +} + +void OPN2_GenerateResampled(ym3438_t *chip, Bit16s *buf) +{ + Bit16s buffer[2]; + + while (chip->samplecnt >= chip->rateratio) + { + chip->oldsamples[0] = chip->samples[0]; + chip->oldsamples[1] = chip->samples[1]; + OPN2_Generate(chip, buffer); + chip->samples[0] = buffer[0] * 11; + chip->samples[1] = buffer[1] * 11; + chip->samplecnt -= chip->rateratio; + } + buf[0] = (Bit16s)(((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) + + chip->samples[0] * chip->samplecnt) / chip->rateratio)>>1); + buf[1] = (Bit16s)(((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) + + chip->samples[1] * chip->samplecnt) / chip->rateratio)>>1); + chip->samplecnt += 1 << RSM_FRAC; +} + +void OPN2_GenerateStream(ym3438_t *chip, Bit16s *output, Bit32u numsamples) +{ + Bit32u i; + Bit16s buffer[2]; + + for (i = 0; i < numsamples; i++) + { + OPN2_GenerateResampled(chip, buffer); + *output++ = buffer[0]; + *output++ = buffer[1]; + } +} + +void OPN2_GenerateStreamMix(ym3438_t *chip, Bit16s *output, Bit32u numsamples) +{ + Bit32u i; + Bit16s buffer[2]; + + for (i = 0; i < numsamples; i++) + { + OPN2_GenerateResampled(chip, buffer); + *output++ += buffer[0]; + *output++ += buffer[1]; + } +} + + +void OPN2_SetOptions(Bit8u flags) +{ + switch ((flags >> 3) & 0x03) + { + case 0x00: /* YM2612 */ + default: + OPN2_SetChipType(ym3438_type_ym2612); + break; + case 0x01: /* ASIC YM3438 */ + OPN2_SetChipType(ym3438_type_asic); + break; + case 0x02: /* Discrete YM3438 */ + OPN2_SetChipType(ym3438_type_discrete); + break; + } +} + +void OPN2_SetMute(ym3438_t *chip, Bit32u mute) +{ + Bit32u i; + for (i = 0; i < 7; i++) + { + chip->mute[i] = (mute >> i) & 0x01; + } +} diff --git a/src/sound/opnmidi/chips/nuked/ym3438.h b/src/sound/opnmidi/chips/nuked/ym3438.h new file mode 100644 index 000000000..c277f087b --- /dev/null +++ b/src/sound/opnmidi/chips/nuked/ym3438.h @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2017 Alexey Khokholov (Nuke.YKT) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + * Nuked OPN2(Yamaha YM3438) emulator. + * Thanks: + * Silicon Pr0n: + * Yamaha YM3438 decap and die shot(digshadow). + * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): + * OPL2 ROMs. + * + * version: 1.0.7 + */ + +#ifndef YM3438_H +#define YM3438_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*EXTRA*/ +#define RSM_FRAC 10 +#define OPN_WRITEBUF_SIZE 2048 +#define OPN_WRITEBUF_DELAY 15 + +enum { + ym3438_type_discrete = 0, /* Discrete YM3438 (Teradrive) */ + ym3438_type_asic = 1, /* ASIC YM3438 (MD1 VA7, MD2, MD3, etc) */ + ym3438_type_ym2612 = 2 /* YM2612 (MD1, MD2 VA2) */ +}; + +#include + +typedef uintptr_t Bitu; +typedef intptr_t Bits; +typedef uint64_t Bit64u; +typedef int64_t Bit64s; +typedef uint32_t Bit32u; +typedef int32_t Bit32s; +typedef uint16_t Bit16u; +typedef int16_t Bit16s; +typedef uint8_t Bit8u; +typedef int8_t Bit8s; + +/*EXTRA*/ +typedef struct _opn2_writebuf { + Bit64u time; + Bit8u port; + Bit8u data; + Bit8u reserved[6]; +} opn2_writebuf; + +typedef struct +{ + Bit32u cycles; + Bit32u channel; + Bit16s mol, mor; + /* IO */ + Bit16u write_data; + Bit8u write_a; + Bit8u write_d; + Bit8u write_a_en; + Bit8u write_d_en; + Bit8u write_busy; + Bit8u write_busy_cnt; + Bit8u write_fm_address; + Bit8u write_fm_data; + Bit8u write_fm_mode_a; + Bit16u address; + Bit8u data; + Bit8u pin_test_in; + Bit8u pin_irq; + Bit8u busy; + /* LFO */ + Bit8u lfo_en; + Bit8u lfo_freq; + Bit8u lfo_pm; + Bit8u lfo_am; + Bit8u lfo_cnt; + Bit8u lfo_inc; + Bit8u lfo_quotient; + /* Phase generator */ + Bit16u pg_fnum; + Bit8u pg_block; + Bit8u pg_kcode; + Bit32u pg_inc[24]; + Bit32u pg_phase[24]; + Bit8u pg_reset[24]; + Bit32u pg_read; + /* Envelope generator */ + Bit8u eg_cycle; + Bit8u eg_cycle_stop; + Bit8u eg_shift; + Bit8u eg_shift_lock; + Bit8u eg_timer_low_lock; + Bit16u eg_timer; + Bit8u eg_timer_inc; + Bit16u eg_quotient; + Bit8u eg_custom_timer; + Bit8u eg_rate; + Bit8u eg_ksv; + Bit8u eg_inc; + Bit8u eg_ratemax; + Bit8u eg_sl[2]; + Bit8u eg_lfo_am; + Bit8u eg_tl[2]; + Bit8u eg_state[24]; + Bit16u eg_level[24]; + Bit16u eg_out[24]; + Bit8u eg_kon[24]; + Bit8u eg_kon_csm[24]; + Bit8u eg_kon_latch[24]; + Bit8u eg_csm_mode[24]; + Bit8u eg_ssg_enable[24]; + Bit8u eg_ssg_pgrst_latch[24]; + Bit8u eg_ssg_repeat_latch[24]; + Bit8u eg_ssg_hold_up_latch[24]; + Bit8u eg_ssg_dir[24]; + Bit8u eg_ssg_inv[24]; + Bit32u eg_read[2]; + Bit8u eg_read_inc; + /* FM */ + Bit16s fm_op1[6][2]; + Bit16s fm_op2[6]; + Bit16s fm_out[24]; + Bit16u fm_mod[24]; + /* Channel */ + Bit16s ch_acc[6]; + Bit16s ch_out[6]; + Bit16s ch_lock; + Bit8u ch_lock_l; + Bit8u ch_lock_r; + Bit16s ch_read; + /* Timer */ + Bit16u timer_a_cnt; + Bit16u timer_a_reg; + Bit8u timer_a_load_lock; + Bit8u timer_a_load; + Bit8u timer_a_enable; + Bit8u timer_a_reset; + Bit8u timer_a_load_latch; + Bit8u timer_a_overflow_flag; + Bit8u timer_a_overflow; + + Bit16u timer_b_cnt; + Bit8u timer_b_subcnt; + Bit16u timer_b_reg; + Bit8u timer_b_load_lock; + Bit8u timer_b_load; + Bit8u timer_b_enable; + Bit8u timer_b_reset; + Bit8u timer_b_load_latch; + Bit8u timer_b_overflow_flag; + Bit8u timer_b_overflow; + + /* Register set */ + Bit8u mode_test_21[8]; + Bit8u mode_test_2c[8]; + Bit8u mode_ch3; + Bit8u mode_kon_channel; + Bit8u mode_kon_operator[4]; + Bit8u mode_kon[24]; + Bit8u mode_csm; + Bit8u mode_kon_csm; + Bit8u dacen; + Bit16s dacdata; + + Bit8u ks[24]; + Bit8u ar[24]; + Bit8u sr[24]; + Bit8u dt[24]; + Bit8u multi[24]; + Bit8u sl[24]; + Bit8u rr[24]; + Bit8u dr[24]; + Bit8u am[24]; + Bit8u tl[24]; + Bit8u ssg_eg[24]; + + Bit16u fnum[6]; + Bit8u block[6]; + Bit8u kcode[6]; + Bit16u fnum_3ch[6]; + Bit8u block_3ch[6]; + Bit8u kcode_3ch[6]; + Bit8u reg_a4; + Bit8u reg_ac; + Bit8u connect[6]; + Bit8u fb[6]; + Bit8u pan_l[6], pan_r[6]; + Bit8u ams[6]; + Bit8u pms[6]; + + /*EXTRA*/ + Bit32u mute[7]; + Bit32s rateratio; + Bit32s samplecnt; + Bit32s oldsamples[2]; + Bit32s samples[2]; + + Bit64u writebuf_samplecnt; + Bit32u writebuf_cur; + Bit32u writebuf_last; + Bit64u writebuf_lasttime; + opn2_writebuf writebuf[OPN_WRITEBUF_SIZE]; +} ym3438_t; + +/* EXTRA, original was "void OPN2_Reset(ym3438_t *chip)" */ +void OPN2_Reset(ym3438_t *chip, Bit32u rate, Bit32u clock); +void OPN2_SetChipType(Bit32u type); +void OPN2_Clock(ym3438_t *chip, Bit16s *buffer); +void OPN2_Write(ym3438_t *chip, Bit32u port, Bit8u data); +void OPN2_SetTestPin(ym3438_t *chip, Bit32u value); +Bit32u OPN2_ReadTestPin(ym3438_t *chip); +Bit32u OPN2_ReadIRQPin(ym3438_t *chip); +Bit8u OPN2_Read(ym3438_t *chip, Bit32u port); + +/*EXTRA*/ +void OPN2_WriteBuffered(ym3438_t *chip, Bit32u port, Bit8u data); +void OPN2_Generate(ym3438_t *chip, Bit16s *buf); +void OPN2_GenerateResampled(ym3438_t *chip, Bit16s *buf); +void OPN2_GenerateStream(ym3438_t *chip, Bit16s *output, Bit32u numsamples); +void OPN2_GenerateStreamMix(ym3438_t *chip, Bit16s *output, Bit32u numsamples); +void OPN2_SetOptions(Bit8u flags); +void OPN2_SetMute(ym3438_t *chip, Bit32u mute); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/sound/opnmidi/chips/nuked_opn2.cpp b/src/sound/opnmidi/chips/nuked_opn2.cpp new file mode 100644 index 000000000..e452ccf0f --- /dev/null +++ b/src/sound/opnmidi/chips/nuked_opn2.cpp @@ -0,0 +1,49 @@ +#include "nuked_opn2.h" +#include "nuked/ym3438.h" +#include + +NukedOPN2::NukedOPN2() +{ + OPN2_SetChipType(ym3438_type_asic); + chip = new ym3438_t; + setRate(m_rate, m_clock); +} + +NukedOPN2::~NukedOPN2() +{ + ym3438_t *chip_r = reinterpret_cast(chip); + delete chip_r; +} + +void NukedOPN2::setRate(uint32_t rate, uint32_t clock) +{ + OPNChipBaseT::setRate(rate, clock); + ym3438_t *chip_r = reinterpret_cast(chip); + OPN2_Reset(chip_r, rate, clock); +} + +void NukedOPN2::reset() +{ + OPNChipBaseT::reset(); + ym3438_t *chip_r = reinterpret_cast(chip); + OPN2_Reset(chip_r, m_rate, m_clock); +} + +void NukedOPN2::writeReg(uint32_t port, uint16_t addr, uint8_t data) +{ + ym3438_t *chip_r = reinterpret_cast(chip); + OPN2_WriteBuffered(chip_r, 0 + (port) * 2, (uint8_t)addr); + OPN2_WriteBuffered(chip_r, 1 + (port) * 2, data); + //qDebug() << QString("%1: 0x%2 => 0x%3").arg(port).arg(addr, 2, 16, QChar('0')).arg(data, 2, 16, QChar('0')); +} + +void NukedOPN2::nativeGenerate(int16_t *frame) +{ + ym3438_t *chip_r = reinterpret_cast(chip); + OPN2_Generate(chip_r, frame); +} + +const char *NukedOPN2::emulatorName() +{ + return "Nuked OPN2"; +} diff --git a/src/sound/opnmidi/chips/nuked_opn2.h b/src/sound/opnmidi/chips/nuked_opn2.h new file mode 100644 index 000000000..9eb239f48 --- /dev/null +++ b/src/sound/opnmidi/chips/nuked_opn2.h @@ -0,0 +1,25 @@ +#ifndef NUKED_OPN2_H +#define NUKED_OPN2_H + +#include "opn_chip_base.h" + +class NukedOPN2 final : public OPNChipBaseT +{ + void *chip; +public: + NukedOPN2(); + ~NukedOPN2() override; + + bool canRunAtPcmRate() const override { return false; } + void setRate(uint32_t rate, uint32_t clock) override; + void reset() override; + void writeReg(uint32_t port, uint16_t addr, uint8_t data) override; + void nativePreGenerate() override {} + void nativePostGenerate() override {} + void nativeGenerate(int16_t *frame) override; + const char *emulatorName() override; + // amplitude scale factors to use in resampling + enum { resamplerPreAmplify = 11, resamplerPostAttenuate = 2 }; +}; + +#endif // NUKED_OPN2_H diff --git a/src/sound/opnmidi/chips/opn_chip_base.h b/src/sound/opnmidi/chips/opn_chip_base.h new file mode 100644 index 000000000..5c532c920 --- /dev/null +++ b/src/sound/opnmidi/chips/opn_chip_base.h @@ -0,0 +1,110 @@ +#ifndef ONP_CHIP_BASE_H +#define ONP_CHIP_BASE_H + +#include +#include + +#if !defined(_MSC_VER) && (__cplusplus <= 199711L) +#define final +#define override +#endif + +#if defined(OPNMIDI_ENABLE_HQ_RESAMPLER) +class VResampler; +#endif + +class OPNChipBase +{ +public: + enum { nativeRate = 53267 }; +protected: + uint32_t m_rate; + uint32_t m_clock; +public: + OPNChipBase(); + virtual ~OPNChipBase(); + + virtual bool canRunAtPcmRate() const = 0; + virtual bool isRunningAtPcmRate() const = 0; + virtual bool setRunningAtPcmRate(bool r) = 0; + + virtual void setRate(uint32_t rate, uint32_t clock) = 0; + virtual void reset() = 0; + virtual void writeReg(uint32_t port, uint16_t addr, uint8_t data) = 0; + + virtual void nativePreGenerate() = 0; + virtual void nativePostGenerate() = 0; + virtual void nativeGenerate(int16_t *frame) = 0; + + virtual void generate(int16_t *output, size_t frames) = 0; + virtual void generateAndMix(int16_t *output, size_t frames) = 0; + virtual void generate32(int32_t *output, size_t frames) = 0; + virtual void generateAndMix32(int32_t *output, size_t frames) = 0; + + virtual const char* emulatorName() = 0; +private: + OPNChipBase(const OPNChipBase &c); + OPNChipBase &operator=(const OPNChipBase &c); +}; + +// A base class providing F-bounded generic and efficient implementations, +// supporting resampling of chip outputs +template +class OPNChipBaseT : public OPNChipBase +{ +public: + OPNChipBaseT(); + virtual ~OPNChipBaseT(); + + bool isRunningAtPcmRate() const override; + bool setRunningAtPcmRate(bool r) override; + + virtual void setRate(uint32_t rate, uint32_t clock) override; + virtual void reset() override; + void generate(int16_t *output, size_t frames) override; + void generateAndMix(int16_t *output, size_t frames) override; + void generate32(int32_t *output, size_t frames) override; + void generateAndMix32(int32_t *output, size_t frames) override; +private: + bool m_runningAtPcmRate; + void setupResampler(uint32_t rate); + void resetResampler(); + void resampledGenerate(int32_t *output); +#if defined(OPNMIDI_ENABLE_HQ_RESAMPLER) + VResampler *m_resampler; +#else + int32_t m_oldsamples[2]; + int32_t m_samples[2]; + int32_t m_samplecnt; + int32_t m_rateratio; + enum { rsm_frac = 10 }; +#endif + // amplitude scale factors in and out of resampler, varying for chips; + // values are OK to "redefine", the static polymorphism will accept it. + enum { resamplerPreAmplify = 1, resamplerPostAttenuate = 1 }; +}; + +// A base class which provides frame-by-frame interfaces on emulations which +// don't have a routine for it. It produces outputs in fixed size buffers. +// Fast register updates will suffer some latency because of buffering. +template +class OPNChipBaseBufferedT : public OPNChipBaseT +{ +public: + OPNChipBaseBufferedT() + : OPNChipBaseT(), m_bufferIndex(0) {} + virtual ~OPNChipBaseBufferedT() + {} +public: + void reset() override; + void nativeGenerate(int16_t *frame) override; +protected: + virtual void nativeGenerateN(int16_t *output, size_t frames) = 0; +private: + unsigned m_bufferIndex; + int16_t m_buffer[2 * Buffer]; +}; + +#include "opn_chip_base.tcc" + +#endif // ONP_CHIP_BASE_H diff --git a/src/sound/opnmidi/chips/opn_chip_base.tcc b/src/sound/opnmidi/chips/opn_chip_base.tcc new file mode 100644 index 000000000..4915e802d --- /dev/null +++ b/src/sound/opnmidi/chips/opn_chip_base.tcc @@ -0,0 +1,268 @@ +#include "opn_chip_base.h" +#include + +#if defined(OPNMIDI_ENABLE_HQ_RESAMPLER) +#include +#endif + +#if !defined(LIKELY) && defined(__GNUC__) +#define LIKELY(x) __builtin_expect((x), 1) +#elif !defined(LIKELY) +#define LIKELY(x) (x) +#endif + +#if !defined(UNLIKELY) && defined(__GNUC__) +#define UNLIKELY(x) __builtin_expect((x), 0) +#elif !defined(UNLIKELY) +#define UNLIKELY(x) (x) +#endif + +/* OPNChipBase */ + +inline OPNChipBase::OPNChipBase() : + m_rate(44100), + m_clock(7670454) +{ +} + +inline OPNChipBase::~OPNChipBase() +{ +} + +/* OPNChipBaseT */ + +template +OPNChipBaseT::OPNChipBaseT() + : OPNChipBase(), + m_runningAtPcmRate(false) +{ +#if defined(OPNMIDI_ENABLE_HQ_RESAMPLER) + m_resampler = new VResampler; +#endif + setupResampler(m_rate); +} + +template +OPNChipBaseT::~OPNChipBaseT() +{ +#if defined(OPNMIDI_ENABLE_HQ_RESAMPLER) + delete m_resampler; +#endif +} + +template +bool OPNChipBaseT::isRunningAtPcmRate() const +{ + return m_runningAtPcmRate; +} + +template +bool OPNChipBaseT::setRunningAtPcmRate(bool r) +{ + if(r != m_runningAtPcmRate) + { + if(r && !static_cast(this)->canRunAtPcmRate()) + return false; + m_runningAtPcmRate = r; + static_cast(this)->setRate(m_rate, m_clock); + } + return true; +} + +template +void OPNChipBaseT::setRate(uint32_t rate, uint32_t clock) +{ + uint32_t oldRate = m_rate; + m_rate = rate; + m_clock = clock; + if(rate != oldRate) + setupResampler(rate); + else + resetResampler(); +} + +template +void OPNChipBaseT::reset() +{ + resetResampler(); +} + +template +void OPNChipBaseT::generate(int16_t *output, size_t frames) +{ + static_cast(this)->nativePreGenerate(); + for(size_t i = 0; i < frames; ++i) + { + int32_t frame[2]; + static_cast(this)->resampledGenerate(frame); + for (unsigned c = 0; c < 2; ++c) { + int32_t temp = frame[c]; + temp = (temp > -32768) ? temp : -32768; + temp = (temp < 32767) ? temp : 32767; + output[c] = (int16_t)temp; + } + output += 2; + } + static_cast(this)->nativePostGenerate(); +} + +template +void OPNChipBaseT::generateAndMix(int16_t *output, size_t frames) +{ + static_cast(this)->nativePreGenerate(); + for(size_t i = 0; i < frames; ++i) + { + int32_t frame[2]; + static_cast(this)->resampledGenerate(frame); + for (unsigned c = 0; c < 2; ++c) { + int32_t temp = (int32_t)output[c] + frame[c]; + temp = (temp > -32768) ? temp : -32768; + temp = (temp < 32767) ? temp : 32767; + output[c] = (int16_t)temp; + } + output += 2; + } + static_cast(this)->nativePostGenerate(); +} + +template +void OPNChipBaseT::generate32(int32_t *output, size_t frames) +{ + static_cast(this)->nativePreGenerate(); + for(size_t i = 0; i < frames; ++i) + { + static_cast(this)->resampledGenerate(output); + output += 2; + } + static_cast(this)->nativePostGenerate(); +} + +template +void OPNChipBaseT::generateAndMix32(int32_t *output, size_t frames) +{ + static_cast(this)->nativePreGenerate(); + for(size_t i = 0; i < frames; ++i) + { + int32_t frame[2]; + static_cast(this)->resampledGenerate(frame); + output[0] += frame[0]; + output[1] += frame[1]; + output += 2; + } + static_cast(this)->nativePostGenerate(); +} + +template +void OPNChipBaseT::setupResampler(uint32_t rate) +{ +#if defined(OPNMIDI_ENABLE_HQ_RESAMPLER) + m_resampler->setup(rate * (1.0 / 53267), 2, 48); +#else + m_oldsamples[0] = m_oldsamples[1] = 0; + m_samples[0] = m_samples[1] = 0; + m_samplecnt = 0; + m_rateratio = (int32_t)(uint32_t)((((uint64_t)144 * rate) << rsm_frac) / m_clock); +#endif +} + +template +void OPNChipBaseT::resetResampler() +{ +#if defined(OPNMIDI_ENABLE_HQ_RESAMPLER) + m_resampler->reset(); +#else + m_oldsamples[0] = m_oldsamples[1] = 0; + m_samples[0] = m_samples[1] = 0; + m_samplecnt = 0; +#endif +} + +#if defined(OPNMIDI_ENABLE_HQ_RESAMPLER) +template +void OPNChipBaseT::resampledGenerate(int32_t *output) +{ + if(UNLIKELY(m_runningAtPcmRate)) + { + int16_t in[2]; + static_cast(this)->nativeGenerate(in); + output[0] = (int32_t)in[0] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + output[1] = (int32_t)in[1] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + return; + } + + VResampler *rsm = m_resampler; + float scale = (float)T::resamplerPreAmplify / + (float)T::resamplerPostAttenuate; + float f_in[2]; + float f_out[2]; + rsm->inp_count = 0; + rsm->inp_data = f_in; + rsm->out_count = 1; + rsm->out_data = f_out; + while(rsm->process(), rsm->out_count != 0) + { + int16_t in[2]; + static_cast(this)->nativeGenerate(in); + f_in[0] = scale * (float)in[0]; + f_in[1] = scale * (float)in[1]; + rsm->inp_count = 1; + rsm->inp_data = f_in; + rsm->out_count = 1; + rsm->out_data = f_out; + } + output[0] = std::lround(f_out[0]); + output[1] = std::lround(f_out[1]); +} +#else +template +void OPNChipBaseT::resampledGenerate(int32_t *output) +{ + if(UNLIKELY(m_runningAtPcmRate)) + { + int16_t in[2]; + static_cast(this)->nativeGenerate(in); + output[0] = (int32_t)in[0] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + output[1] = (int32_t)in[1] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + return; + } + + int32_t samplecnt = m_samplecnt; + const int32_t rateratio = m_rateratio; + while(samplecnt >= rateratio) + { + m_oldsamples[0] = m_samples[0]; + m_oldsamples[1] = m_samples[1]; + int16_t buffer[2]; + static_cast(this)->nativeGenerate(buffer); + m_samples[0] = buffer[0] * T::resamplerPreAmplify; + m_samples[1] = buffer[1] * T::resamplerPreAmplify; + samplecnt -= rateratio; + } + output[0] = (int32_t)(((m_oldsamples[0] * (rateratio - samplecnt) + + m_samples[0] * samplecnt) / rateratio)/T::resamplerPostAttenuate); + output[1] = (int32_t)(((m_oldsamples[1] * (rateratio - samplecnt) + + m_samples[1] * samplecnt) / rateratio)/T::resamplerPostAttenuate); + m_samplecnt = samplecnt + (1 << rsm_frac); +} +#endif + +/* OPNChipBaseBufferedT */ + +template +void OPNChipBaseBufferedT::reset() +{ + OPNChipBaseT::reset(); + m_bufferIndex = 0; +} + +template +void OPNChipBaseBufferedT::nativeGenerate(int16_t *frame) +{ + unsigned bufferIndex = m_bufferIndex; + if(bufferIndex == 0) + static_cast(this)->nativeGenerateN(m_buffer, Buffer); + frame[0] = m_buffer[2 * bufferIndex]; + frame[1] = m_buffer[2 * bufferIndex + 1]; + bufferIndex = (bufferIndex + 1 < Buffer) ? (bufferIndex + 1) : 0; + m_bufferIndex = bufferIndex; +} diff --git a/src/sound/opnmidi/fraction.hpp b/src/sound/opnmidi/fraction.hpp index 1ec10ab57..7aab95bd2 100644 --- a/src/sound/opnmidi/fraction.hpp +++ b/src/sound/opnmidi/fraction.hpp @@ -82,6 +82,10 @@ public: self &operator= (long double orig); }; +#ifdef _MSC_VER +#pragma warning(disable:4146) +#endif + template void fraction::Optim() { @@ -110,6 +114,10 @@ void fraction::Optim() //fprintf(stderr, "result: %d/%d\n\n", nom(), denom()); } +#ifdef _MSC_VER +#pragma warning(default:4146) +#endif + template inline const fraction abs(const fraction &f) { diff --git a/src/sound/opnmidi/opnbank.h b/src/sound/opnmidi/opnbank.h index fcf3abb77..521616ae1 100644 --- a/src/sound/opnmidi/opnbank.h +++ b/src/sound/opnmidi/opnbank.h @@ -21,6 +21,10 @@ * along with this program. If not, see . */ +#ifndef OPNMIDI_OPNBANK_H +#define OPNMIDI_OPNBANK_H + +#include #include #ifdef ADLMIDI_buildAsApp @@ -36,13 +40,25 @@ public: }; #endif +enum { opnNoteOnMaxTime = 40000 }; + /* *********** FM Operator indexes *********** */ -#define OPERATOR1 0 -#define OPERATOR2 1 -#define OPERATOR3 2 -#define OPERATOR4 3 +enum +{ + OPERATOR1 = 0, + OPERATOR2 = 1, + OPERATOR3 = 2, + OPERATOR4 = 3, +}; /* *********** FM Operator indexes *end******* */ +#pragma pack(push, 1) +#define OPNDATA_BYTE_COMPARABLE(T) \ + inline bool operator==(const T &a, const T &b) \ + { return !memcmp(&a, &b, sizeof(T)); } \ + inline bool operator!=(const T &a, const T &b) \ + { return !operator==(a, b); } + struct OPN_Operator { //! Raw register data @@ -58,6 +74,7 @@ struct OPN_Operator 6 - SSG-EG byte */ }; +OPNDATA_BYTE_COMPARABLE(struct OPN_Operator) struct opnInstData { @@ -68,6 +85,7 @@ struct opnInstData //! Note offset int16_t finetune; }; +OPNDATA_BYTE_COMPARABLE(struct opnInstData) struct opnInstMeta { @@ -79,3 +97,41 @@ struct opnInstMeta uint16_t ms_sound_koff; double fine_tune; }; +OPNDATA_BYTE_COMPARABLE(struct opnInstMeta) + +/** + * @brief Instrument data with operators included + */ +struct opnInstMeta2 +{ + opnInstData opn[2]; + uint8_t tone; + uint8_t flags; + uint16_t ms_sound_kon; // Number of milliseconds it produces sound; + uint16_t ms_sound_koff; + double fine_tune; +#if 0 + opnInstMeta2() {} + explicit opnInstMeta2(const opnInstMeta &d); +#endif +}; +OPNDATA_BYTE_COMPARABLE(struct opnInstMeta2) + +#undef OPNDATA_BYTE_COMPARABLE +#pragma pack(pop) + +#if 0 +/** + * @brief Conversion of storage formats + */ +inline opnInstMeta2::opnInstMeta2(const opnInstMeta &d) + : tone(d.tone), flags(d.flags), + ms_sound_kon(d.ms_sound_kon), ms_sound_koff(d.ms_sound_koff), + fine_tune(d.fine_tune) +{ + opn[0] = ::opn[d.opnno1]; + opn[1] = ::opn[d.opnno2]; +} +#endif + +#endif // OPNMIDI_OPNBANK_H diff --git a/src/sound/opnmidi/opnmidi.cpp b/src/sound/opnmidi/opnmidi.cpp index 6657ee2f5..eab98eee7 100644 --- a/src/sound/opnmidi/opnmidi.cpp +++ b/src/sound/opnmidi/opnmidi.cpp @@ -32,6 +32,13 @@ static OPN2_Version opn2_version = { OPNMIDI_VERSION_PATCHLEVEL }; +static const OPNMIDI_AudioFormat opn2_DefaultAudioFormat = +{ + OPNMIDI_SampleType_S16, + sizeof(int16_t), + 2 * sizeof(int16_t), +}; + /*---------------------------EXPORTS---------------------------*/ OPNMIDI_EXPORT struct OPN2_MIDIPlayer *opn2_init(long sample_rate) @@ -129,7 +136,14 @@ OPNMIDI_EXPORT void opn2_setScaleModulators(OPN2_MIDIPlayer *device, int smod) if(!device) return; OPNMIDIplay *play = reinterpret_cast(device->opn2_midiPlayer); play->m_setup.ScaleModulators = smod; - play->opn.ScaleModulators = play->m_setup.ScaleModulators; + play->opn.ScaleModulators = (play->m_setup.ScaleModulators != 0); +} + +OPNMIDI_EXPORT void opn2_setFullRangeBrightness(struct OPN2_MIDIPlayer *device, int fr_brightness) +{ + if(!device) return; + OPNMIDIplay *play = reinterpret_cast(device->opn2_midiPlayer); + play->m_setup.fullRangeBrightnessCC74 = (fr_brightness != 0); } OPNMIDI_EXPORT void opn2_setLoopEnabled(OPN2_MIDIPlayer *device, int loopEn) @@ -139,12 +153,16 @@ OPNMIDI_EXPORT void opn2_setLoopEnabled(OPN2_MIDIPlayer *device, int loopEn) play->m_setup.loopingIsEnabled = (loopEn != 0); } +/* !!!DEPRECATED!!! */ OPNMIDI_EXPORT void opn2_setLogarithmicVolumes(struct OPN2_MIDIPlayer *device, int logvol) { if(!device) return; OPNMIDIplay *play = reinterpret_cast(device->opn2_midiPlayer); play->m_setup.LogarithmicVolumes = static_cast(logvol); - play->opn.LogarithmicVolumes = play->m_setup.LogarithmicVolumes; + if(play->m_setup.LogarithmicVolumes != 0) + play->opn.ChangeVolumeRangesModel(OPNMIDI_VolumeModel_CMF); + else + play->opn.ChangeVolumeRangesModel(static_cast(play->m_setup.VolumeModel)); } OPNMIDI_EXPORT void opn2_setVolumeRangeModel(OPN2_MIDIPlayer *device, int volumeModel) @@ -209,16 +227,60 @@ OPNMIDI_EXPORT int opn2_openData(OPN2_MIDIPlayer *device, const void *mem, unsig OPNMIDI_EXPORT const char *opn2_emulatorName() { - #ifdef OPNMIDI_USE_LEGACY_EMULATOR - return "GENS 2.10 YM2612"; - #else - return "Nuked OPN2 YM3438"; - #endif + return ""; } +OPNMIDI_EXPORT const char *opn2_chipEmulatorName(struct OPN2_MIDIPlayer *device) +{ + if(device) + { + OPNMIDIplay *play = reinterpret_cast(device->opn2_midiPlayer); + if(play && !play->opn.cardsOP2.empty()) + return play->opn.cardsOP2[0]->emulatorName(); + } + return "Unknown"; +} + +OPNMIDI_EXPORT int opn2_switchEmulator(struct OPN2_MIDIPlayer *device, int emulator) +{ + if(device) + { + OPNMIDIplay *play = reinterpret_cast(device->opn2_midiPlayer); + if(play && (emulator >= 0) && (emulator < OPNMIDI_EMU_end)) + { + play->m_setup.emulator = emulator; + opn2_reset(device); + return 0; + } + play->setErrorString("OPN2 MIDI: Unknown emulation core!"); + } + return -1; +} + + +OPNMIDI_EXPORT int opn2_setRunAtPcmRate(OPN2_MIDIPlayer *device, int enabled) +{ + if(device) + { + OPNMIDIplay *play = reinterpret_cast(device->opn2_midiPlayer); + if(play) + { + play->m_setup.runAtPcmRate = (enabled != 0); + opn2_reset(device); + return 0; + } + } + return -1; +} + + OPNMIDI_EXPORT const char *opn2_linkedLibraryVersion() { +#if !defined(OPNMIDI_ENABLE_HQ_RESAMPLER) return OPNMIDI_VERSION; +#else + return OPNMIDI_VERSION " (HQ)"; +#endif } OPNMIDI_EXPORT const OPN2_Version *opn2_linkedVersion() @@ -270,7 +332,8 @@ OPNMIDI_EXPORT void opn2_reset(OPN2_MIDIPlayer *device) return; OPNMIDIplay *play = reinterpret_cast(device->opn2_midiPlayer); play->m_setup.tick_skip_samples_delay = 0; - play->opn.Reset(play->m_setup.PCM_RATE); + play->opn.runAtPcmRate = play->m_setup.runAtPcmRate; + play->opn.Reset(play->m_setup.emulator, play->m_setup.PCM_RATE); play->ch.clear(); play->ch.resize(play->opn.NumChannels); } @@ -491,24 +554,139 @@ OPNMIDI_EXPORT void opn2_setDebugMessageHook(struct OPN2_MIDIPlayer *device, OPN } +template +static void CopySamplesRaw(OPN2_UInt8 *dstLeft, OPN2_UInt8 *dstRight, const int32_t *src, + size_t frameCount, unsigned sampleOffset) +{ + for(size_t i = 0; i < frameCount; ++i) { + *(Dst *)(dstLeft + (i * sampleOffset)) = src[2 * i]; + *(Dst *)(dstRight + (i * sampleOffset)) = src[(2 * i) + 1]; + } +} -inline static void SendStereoAudio(int &samples_requested, - ssize_t &in_size, - short *_in, - ssize_t out_pos, - short *_out) +template +static void CopySamplesTransformed(OPN2_UInt8 *dstLeft, OPN2_UInt8 *dstRight, const int32_t *src, + size_t frameCount, unsigned sampleOffset, + Ret(&transform)(int32_t)) +{ + for(size_t i = 0; i < frameCount; ++i) { + *(Dst *)(dstLeft + (i * sampleOffset)) = transform(src[2 * i]); + *(Dst *)(dstRight + (i * sampleOffset)) = transform(src[(2 * i) + 1]); + } +} + +static int SendStereoAudio(int samples_requested, + ssize_t in_size, + int32_t *_in, + ssize_t out_pos, + OPN2_UInt8 *left, + OPN2_UInt8 *right, + const OPNMIDI_AudioFormat *format) { if(!in_size) - return; - size_t offset = static_cast(out_pos); + return 0; + size_t outputOffset = static_cast(out_pos); size_t inSamples = static_cast(in_size * 2); - size_t maxSamples = static_cast(samples_requested) - offset; + size_t maxSamples = static_cast(samples_requested) - outputOffset; size_t toCopy = std::min(maxSamples, inSamples); - std::memcpy(_out + out_pos, _in, toCopy * sizeof(short)); + + OPNMIDI_SampleType sampleType = format->type; + const unsigned containerSize = format->containerSize; + const unsigned sampleOffset = format->sampleOffset; + + left += (outputOffset / 2) * sampleOffset; + right += (outputOffset / 2) * sampleOffset; + + typedef int32_t(&pfnConvert)(int32_t); + + switch(sampleType) { + case OPNMIDI_SampleType_S8: + case OPNMIDI_SampleType_U8: + { + pfnConvert cvt = (sampleType == OPNMIDI_SampleType_S8) ? opn2_cvtS8 : opn2_cvtU8; + switch(containerSize) { + case sizeof(int8_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + case sizeof(int16_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + case sizeof(int32_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + default: + return -1; + } + break; + } + case OPNMIDI_SampleType_S16: + case OPNMIDI_SampleType_U16: + { + pfnConvert cvt = (sampleType == OPNMIDI_SampleType_S16) ? opn2_cvtS16 : opn2_cvtU16; + switch(containerSize) { + case sizeof(int16_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + case sizeof(int32_t): + CopySamplesRaw(left, right, _in, toCopy / 2, sampleOffset); + break; + default: + return -1; + } + break; + } + case OPNMIDI_SampleType_S24: + case OPNMIDI_SampleType_U24: + { + pfnConvert cvt = (sampleType == OPNMIDI_SampleType_S24) ? opn2_cvtS24 : opn2_cvtU24; + switch(containerSize) { + case sizeof(int32_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + default: + return -1; + } + break; + } + case OPNMIDI_SampleType_S32: + case OPNMIDI_SampleType_U32: + { + pfnConvert cvt = (sampleType == OPNMIDI_SampleType_S32) ? opn2_cvtS32 : opn2_cvtU32; + switch(containerSize) { + case sizeof(int32_t): + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, cvt); + break; + default: + return -1; + } + break; + } + case OPNMIDI_SampleType_F32: + if(containerSize != sizeof(float)) + return -1; + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, opn2_cvtReal); + break; + case OPNMIDI_SampleType_F64: + if(containerSize != sizeof(double)) + return -1; + CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, opn2_cvtReal); + break; + default: + return -1; + } + + return 0; } -OPNMIDI_EXPORT int opn2_play(OPN2_MIDIPlayer *device, int sampleCount, short *out) +OPNMIDI_EXPORT int opn2_play(struct OPN2_MIDIPlayer *device, int sampleCount, short *out) +{ + return opn2_playFormat(device, sampleCount, (OPN2_UInt8 *)out, (OPN2_UInt8 *)(out + 1), &opn2_DefaultAudioFormat); +} + +OPNMIDI_EXPORT int opn2_playFormat(OPN2_MIDIPlayer *device, int sampleCount, + OPN2_UInt8 *out_left, OPN2_UInt8 *out_right, + const OPNMIDI_AudioFormat *format) { #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER sampleCount -= sampleCount % 2; //Avoid even sample requests @@ -562,31 +740,20 @@ OPNMIDI_EXPORT int opn2_play(OPN2_MIDIPlayer *device, int sampleCount, short *ou ssize_t in_generatedPhys = in_generatedStereo * 2; //! Unsigned total sample count //fill buffer with zeros - int16_t *out_buf = player->outBuf; - std::memset(out_buf, 0, static_cast(in_generatedPhys) * sizeof(int16_t)); + int32_t *out_buf = player->outBuf; + std::memset(out_buf, 0, static_cast(in_generatedPhys) * sizeof(out_buf[0])); unsigned int chips = player->opn.NumCards; if(chips == 1) - { - #ifdef OPNMIDI_USE_LEGACY_EMULATOR - player->opn.cardsOP2[0]->run(int(in_generatedStereo), out_buf); - #else - OPN2_GenerateStream(player->opn.cardsOP2[0], out_buf, (Bit32u)in_generatedStereo); - #endif - } + player->opn.cardsOP2[0]->generate32(out_buf, (size_t)in_generatedStereo); else/* if(n_periodCountStereo > 0)*/ { /* Generate data from every chip and mix result */ - for(unsigned card = 0; card < chips; ++card) - { - #ifdef OPNMIDI_USE_LEGACY_EMULATOR - player->opn.cardsOP2[card]->run(int(in_generatedStereo), out_buf); - #else - OPN2_GenerateStreamMix(player->opn.cardsOP2[card], out_buf, (Bit32u)in_generatedStereo); - #endif - } + for(size_t card = 0; card < chips; ++card) + player->opn.cardsOP2[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo); } /* Process it */ - SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out); + if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1) + return 0; left -= (int)in_generatedPhys; gotten_len += (in_generatedPhys) /* - setup.stored_samples*/; @@ -609,6 +776,13 @@ OPNMIDI_EXPORT int opn2_play(OPN2_MIDIPlayer *device, int sampleCount, short *ou OPNMIDI_EXPORT int opn2_generate(struct OPN2_MIDIPlayer *device, int sampleCount, short *out) +{ + return opn2_generateFormat(device, sampleCount, (OPN2_UInt8 *)out, (OPN2_UInt8 *)(out + 1), &opn2_DefaultAudioFormat); +} + +OPNMIDI_EXPORT int opn2_generateFormat(struct OPN2_MIDIPlayer *device, int sampleCount, + OPN2_UInt8 *out_left, OPN2_UInt8 *out_right, + const OPNMIDI_AudioFormat *format) { sampleCount -= sampleCount % 2; //Avoid even sample requests if(sampleCount < 0) @@ -644,31 +818,20 @@ OPNMIDI_EXPORT int opn2_generate(struct OPN2_MIDIPlayer *device, int sampleCount ssize_t in_generatedPhys = in_generatedStereo * 2; //! Unsigned total sample count //fill buffer with zeros - int16_t *out_buf = player->outBuf; - std::memset(out_buf, 0, static_cast(in_generatedPhys) * sizeof(int16_t)); + int32_t *out_buf = player->outBuf; + std::memset(out_buf, 0, static_cast(in_generatedPhys) * sizeof(out_buf[0])); unsigned int chips = player->opn.NumCards; if(chips == 1) - { - #ifdef OPNMIDI_USE_LEGACY_EMULATOR - player->opn.cardsOP2[0]->run(int(in_generatedStereo), out_buf); - #else - OPN2_GenerateStream(player->opn.cardsOP2[0], out_buf, (Bit32u)in_generatedStereo); - #endif - } + player->opn.cardsOP2[0]->generate32(out_buf, (size_t)in_generatedStereo); else/* if(n_periodCountStereo > 0)*/ { /* Generate data from every chip and mix result */ - for(unsigned card = 0; card < chips; ++card) - { - #ifdef OPNMIDI_USE_LEGACY_EMULATOR - player->opn.cardsOP2[card]->run(int(in_generatedStereo), out_buf); - #else - OPN2_GenerateStreamMix(player->opn.cardsOP2[card], out_buf, (Bit32u)in_generatedStereo); - #endif - } + for(size_t card = 0; card < chips; ++card) + player->opn.cardsOP2[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo); } /* Process it */ - SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out); + if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1) + return 0; left -= (int)in_generatedPhys; gotten_len += (in_generatedPhys) /* - setup.stored_samples*/; diff --git a/src/sound/opnmidi/opnmidi.h b/src/sound/opnmidi/opnmidi.h index f9c61d648..29ac58f86 100644 --- a/src/sound/opnmidi/opnmidi.h +++ b/src/sound/opnmidi/opnmidi.h @@ -29,10 +29,11 @@ extern "C" { #endif #define OPNMIDI_VERSION_MAJOR 1 -#define OPNMIDI_VERSION_MINOR 1 -#define OPNMIDI_VERSION_PATCHLEVEL 1 +#define OPNMIDI_VERSION_MINOR 3 +#define OPNMIDI_VERSION_PATCHLEVEL 0 -#define OPNMIDI_TOSTR(s) #s +#define OPNMIDI_TOSTR_I(s) #s +#define OPNMIDI_TOSTR(s) OPNMIDI_TOSTR_I(s) #define OPNMIDI_VERSION \ OPNMIDI_TOSTR(OPNMIDI_VERSION_MAJOR) "." \ OPNMIDI_TOSTR(OPNMIDI_VERSION_MINOR) "." \ @@ -63,6 +64,28 @@ enum OPNMIDI_VolumeModels OPNMIDI_VolumeModel_9X }; +enum OPNMIDI_SampleType +{ + OPNMIDI_SampleType_S16 = 0, /* signed PCM 16-bit */ + OPNMIDI_SampleType_S8, /* signed PCM 8-bit */ + OPNMIDI_SampleType_F32, /* float 32-bit */ + OPNMIDI_SampleType_F64, /* float 64-bit */ + OPNMIDI_SampleType_S24, /* signed PCM 24-bit */ + OPNMIDI_SampleType_S32, /* signed PCM 32-bit */ + OPNMIDI_SampleType_U8, /* unsigned PCM 8-bit */ + OPNMIDI_SampleType_U16, /* unsigned PCM 16-bit */ + OPNMIDI_SampleType_U24, /* unsigned PCM 24-bit */ + OPNMIDI_SampleType_U32, /* unsigned PCM 32-bit */ + OPNMIDI_SampleType_Count, +}; + +struct OPNMIDI_AudioFormat +{ + enum OPNMIDI_SampleType type; /* type of sample */ + unsigned containerSize; /* size in bytes of the storage type */ + unsigned sampleOffset; /* distance in bytes between consecutive samples */ +}; + struct OPN2_MIDIPlayer { void *opn2_midiPlayer; @@ -80,10 +103,16 @@ extern int opn2_getNumChips(struct OPN2_MIDIPlayer *device); /*Enable or disable Enables scaling of modulator volumes*/ extern void opn2_setScaleModulators(struct OPN2_MIDIPlayer *device, int smod); +/*Enable(1) or Disable(0) full-range brightness (MIDI CC74 used in XG music to filter result sounding) scaling. + By default, brightness affects sound between 0 and 64. + When this option is enabled, the range will use a full range from 0 up to 127. +*/ +extern void opn2_setFullRangeBrightness(struct OPN2_MIDIPlayer *device, int fr_brightness); + /*Enable or disable built-in loop (built-in loop supports 'loopStart' and 'loopEnd' tags to loop specific part)*/ extern void opn2_setLoopEnabled(struct OPN2_MIDIPlayer *device, int loopEn); -/*Enable or disable Logariphmic volume changer (-1 sets default per bank, 0 disable, 1 enable) */ +/* !!!DEPRECATED!!! */ extern void opn2_setLogarithmicVolumes(struct OPN2_MIDIPlayer *device, int logvol); /*Set different volume range model */ @@ -96,15 +125,33 @@ extern int opn2_openBankFile(struct OPN2_MIDIPlayer *device, const char *filePat extern int opn2_openBankData(struct OPN2_MIDIPlayer *device, const void *mem, long size); -/*Returns chip emulator name string*/ +/* DEPRECATED */ extern const char *opn2_emulatorName(); +/*Returns chip emulator name string*/ +extern const char *opn2_chipEmulatorName(struct OPN2_MIDIPlayer *device); + +enum Opn2_Emulator +{ + OPNMIDI_EMU_MAME = 0, + OPNMIDI_EMU_NUKED, + OPNMIDI_EMU_GENS, + OPNMIDI_EMU_GX, + OPNMIDI_EMU_end +}; + +/* Switch the emulation core */ +extern int opn2_switchEmulator(struct OPN2_MIDIPlayer *device, int emulator); + typedef struct { OPN2_UInt16 major; OPN2_UInt16 minor; OPN2_UInt16 patch; } OPN2_Version; +/*Run emulator with PCM rate to reduce CPU usage on slow devices. May decrease sounding accuracy.*/ +extern int opn2_setRunAtPcmRate(struct OPN2_MIDIPlayer *device, int enabled); + /*Returns string which contains a version number*/ extern const char *opn2_linkedLibraryVersion(); @@ -186,11 +233,17 @@ extern struct Opn2_MarkerEntry opn2_metaMarker(struct OPN2_MIDIPlayer *device, s /*Take a sample buffer and iterate MIDI timers */ -extern int opn2_play(struct OPN2_MIDIPlayer *device, int sampleCount, short out[]); +extern int opn2_play(struct OPN2_MIDIPlayer *device, int sampleCount, short *out); + +/*Take a sample buffer and iterate MIDI timers */ +extern int opn2_playFormat(struct OPN2_MIDIPlayer *device, int sampleCount, OPN2_UInt8 *left, OPN2_UInt8 *right, const struct OPNMIDI_AudioFormat *format); /*Generate audio output from chip emulators without iteration of MIDI timers.*/ extern int opn2_generate(struct OPN2_MIDIPlayer *device, int sampleCount, short *out); +/*Generate audio output from chip emulators without iteration of MIDI timers.*/ +extern int opn2_generateFormat(struct OPN2_MIDIPlayer *device, int sampleCount, OPN2_UInt8 *left, OPN2_UInt8 *right, const struct OPNMIDI_AudioFormat *format); + /** * @brief Periodic tick handler. * @param device diff --git a/src/sound/opnmidi/opnmidi_bankmap.h b/src/sound/opnmidi/opnmidi_bankmap.h new file mode 100644 index 000000000..eb05566bc --- /dev/null +++ b/src/sound/opnmidi/opnmidi_bankmap.h @@ -0,0 +1,127 @@ +/* + * libOPNMIDI is a free MIDI to WAV conversion library with OPN2 (YM2612) emulation + * + * MIDI parser and player (Original code from ADLMIDI): Copyright (c) 2010-2014 Joel Yliluoma + * ADLMIDI Library API: Copyright (c) 2015-2018 Vitaly Novichkov + * + * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation: + * http://iki.fi/bisqwit/source/adlmidi.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef OPNMIDI_BANKMAP_H +#define OPNMIDI_BANKMAP_H + +#include +#include +#include +#include + +#include "opnmidi_ptr.hpp" + +/** + * A simple hash map which accepts bank numbers as keys, can be reserved to a + * fixed size, offers O(1) search and insertion, has a hash function to + * optimize for the worst case, and has some good cache locality properties. + */ +template +class BasicBankMap +{ +public: + typedef uint16_t key_type; /* the bank identifier */ + typedef T mapped_type; + typedef std::pair value_type; + + BasicBankMap(); + void reserve(size_t capacity); + + size_t size() const + { return m_size; } + size_t capacity() const + { return m_capacity; } + bool empty() const + { return m_size == 0; } + + class iterator; + iterator begin() const; + iterator end() const; + + struct do_not_expand_t {}; + + iterator find(key_type key); + void erase(iterator it); + std::pair insert(const value_type &value); + std::pair insert(const value_type &value, do_not_expand_t); + void clear(); + + T &operator[](key_type key); + +private: + struct Slot; + enum { minimum_allocation = 4 }; + enum + { + hash_bits = 8, /* worst case # of collisions: 128^2/2^hash_bits */ + hash_buckets = 1 << hash_bits, + }; + +public: + class iterator + { + public: + iterator(); + value_type &operator*() const { return slot->value; } + value_type *operator->() const { return &slot->value; } + iterator &operator++(); + bool operator==(const iterator &o) const; + bool operator!=(const iterator &o) const; + void to_ptrs(void *ptrs[3]); + static iterator from_ptrs(void *const ptrs[3]); + private: + Slot **buckets; + Slot *slot; + size_t index; + iterator(Slot **buckets, Slot *slot, size_t index); +#ifdef _MSC_VER + template + friend class BasicBankMap; +#else + friend class BasicBankMap; +#endif + }; + +private: + struct Slot { + Slot *next, *prev; + value_type value; + Slot() : next(NULL), prev(NULL) {} + }; + AdlMIDI_SPtrArray m_buckets; + std::list< AdlMIDI_SPtrArray > m_allocations; + Slot *m_freeslots; + size_t m_size; + size_t m_capacity; + static size_t hash(key_type key); + Slot *allocate_slot(); + Slot *ensure_allocate_slot(); + void free_slot(Slot *slot); + Slot *bucket_find(size_t index, key_type key); + void bucket_add(size_t index, Slot *slot); + void bucket_remove(size_t index, Slot *slot); +}; + +#include "opnmidi_bankmap.tcc" + +#endif // OPNMIDI_BANKMAP_H diff --git a/src/sound/opnmidi/opnmidi_bankmap.tcc b/src/sound/opnmidi/opnmidi_bankmap.tcc new file mode 100644 index 000000000..80ced116b --- /dev/null +++ b/src/sound/opnmidi/opnmidi_bankmap.tcc @@ -0,0 +1,283 @@ +/* + * libOPNMIDI is a free MIDI to WAV conversion library with OPN2 (YM2612) emulation + * + * MIDI parser and player (Original code from ADLMIDI): Copyright (c) 2010-2014 Joel Yliluoma + * ADLMIDI Library API: Copyright (c) 2015-2018 Vitaly Novichkov + * + * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation: + * http://iki.fi/bisqwit/source/adlmidi.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "opnmidi_bankmap.h" +#include + +template +inline BasicBankMap::BasicBankMap() + : m_freeslots(NULL), + m_size(0), + m_capacity(0) +{ + m_buckets.reset(new Slot *[hash_buckets]()); +} + +template +inline size_t BasicBankMap::hash(key_type key) +{ + // disregard the 0 high bit in LSB + key = (key & 127) | ((key >> 8) << 7); + // take low part as hash value + return key & (hash_buckets - 1); +} + +template +void BasicBankMap::reserve(size_t capacity) +{ + if(m_capacity >= capacity) + return; + + size_t need = capacity - m_capacity; + const size_t minalloc = static_cast(minimum_allocation); + need = (need < minalloc) ? minalloc : need; + + AdlMIDI_SPtrArray slotz; + slotz.reset(new Slot[need]); + m_allocations.push_back(slotz); + m_capacity += need; + + for(size_t i = need; i-- > 0;) + free_slot(&slotz[i]); +} + +template +typename BasicBankMap::iterator +BasicBankMap::begin() const +{ + iterator it(m_buckets.get(), NULL, 0); + while(it.index < hash_buckets && !(it.slot = m_buckets[it.index])) + ++it.index; + return it; +} + +template +typename BasicBankMap::iterator +BasicBankMap::end() const +{ + iterator it(m_buckets.get(), NULL, hash_buckets); + return it; +} + +template +typename BasicBankMap::iterator BasicBankMap::find(key_type key) +{ + size_t index = hash(key); + Slot *slot = bucket_find(index, key); + if(!slot) + return end(); + return iterator(m_buckets.get(), slot, index); +} + +template +void BasicBankMap::erase(iterator it) +{ + bucket_remove(it.index, it.slot); + free_slot(it.slot); + --m_size; +} + +template +inline BasicBankMap::iterator::iterator() + : buckets(NULL), slot(NULL), index(0) +{ +} + +template +inline BasicBankMap::iterator::iterator(Slot **buckets, Slot *slot, size_t index) + : buckets(buckets), slot(slot), index(index) +{ +} + +template +typename BasicBankMap::iterator & +BasicBankMap::iterator::operator++() +{ + if(slot->next) + slot = slot->next; + else { + Slot *slot = NULL; + ++index; + while(index < hash_buckets && !(slot = buckets[index])) + ++index; + this->slot = slot; + } + return *this; +} + +template +bool BasicBankMap::iterator::operator==(const iterator &o) const +{ + return buckets == o.buckets && slot == o.slot && index == o.index; +} + +template +inline bool BasicBankMap::iterator::operator!=(const iterator &o) const +{ + return !operator==(o); +} + +template +void BasicBankMap::iterator::to_ptrs(void *ptrs[3]) +{ + ptrs[0] = buckets; + ptrs[1] = slot; + ptrs[2] = (void *)index; +} + +template +typename BasicBankMap::iterator +BasicBankMap::iterator::from_ptrs(void *const ptrs[3]) +{ + iterator it; + it.buckets = (Slot **)ptrs[0]; + it.slot = (Slot *)ptrs[1]; + it.index = (size_t)ptrs[2]; + return it; +} + +template +std::pair::iterator, bool> +BasicBankMap::insert(const value_type &value) +{ + size_t index = hash(value.first); + Slot *slot = bucket_find(index, value.first); + if(slot) + return std::make_pair(iterator(m_buckets.get(), slot, index), false); + slot = allocate_slot(); + if(!slot) { + reserve(m_capacity + minimum_allocation); + slot = ensure_allocate_slot(); + } + slot->value = value; + bucket_add(index, slot); + ++m_size; + return std::make_pair(iterator(m_buckets.get(), slot, index), true); +} + +template +std::pair::iterator, bool> +BasicBankMap::insert(const value_type &value, do_not_expand_t) +{ + size_t index = hash(value.first); + Slot *slot = bucket_find(index, value.first); + if(slot) + return std::make_pair(iterator(m_buckets.get(), slot, index), false); + slot = allocate_slot(); + if(!slot) + return std::make_pair(end(), false); + slot->value = value; + bucket_add(index, slot); + ++m_size; + return std::make_pair(iterator(m_buckets.get(), slot, index), true); +} + +template +void BasicBankMap::clear() +{ + for(size_t i = 0; i < hash_buckets; ++i) { + Slot *slot = m_buckets[i]; + while (Slot *cur = slot) { + slot = slot->next; + free_slot(cur); + } + m_buckets[i] = NULL; + } + m_size = 0; +} + +template +inline T &BasicBankMap::operator[](key_type key) +{ + return insert(value_type(key, T())).first->second; +} + +template +typename BasicBankMap::Slot * +BasicBankMap::allocate_slot() +{ + Slot *slot = m_freeslots; + if(!slot) + return NULL; + Slot *next = slot->next; + if(next) + next->prev = NULL; + m_freeslots = next; + return slot; +} + +template +inline typename BasicBankMap::Slot * +BasicBankMap::ensure_allocate_slot() +{ + Slot *slot = allocate_slot(); + assert(slot); + return slot; +} + +template +void BasicBankMap::free_slot(Slot *slot) +{ + Slot *next = m_freeslots; + if(next) + next->prev = slot; + slot->prev = NULL; + slot->next = next; + m_freeslots = slot; + m_freeslots->value.second = T(); +} + +template +typename BasicBankMap::Slot * +BasicBankMap::bucket_find(size_t index, key_type key) +{ + Slot *slot = m_buckets[index]; + while(slot && slot->value.first != key) + slot = slot->next; + return slot; +} + +template +void BasicBankMap::bucket_add(size_t index, Slot *slot) +{ + assert(slot); + Slot *next = m_buckets[index]; + if(next) + next->prev = slot; + slot->next = next; + m_buckets[index] = slot; +} + +template +void BasicBankMap::bucket_remove(size_t index, Slot *slot) +{ + assert(slot); + Slot *prev = slot->prev; + Slot *next = slot->next; + if(!prev) + m_buckets[index] = next; + else + prev->next = next; + if(next) + next->prev = prev; +} diff --git a/src/sound/opnmidi/opnmidi_load.cpp b/src/sound/opnmidi/opnmidi_load.cpp index 15d0a5d35..c52b8093c 100644 --- a/src/sound/opnmidi/opnmidi_load.cpp +++ b/src/sound/opnmidi/opnmidi_load.cpp @@ -161,7 +161,7 @@ bool OPNMIDIplay::LoadBank(OPNMIDIplay::fileReader &fr) uint16_t version = 1; uint16_t count_melodic_banks = 1; - uint16_t count_percusive_banks = 1; + uint16_t count_percussive_banks = 1; if(fr.read(magic, 1, 11) != 11) { @@ -194,15 +194,14 @@ bool OPNMIDIplay::LoadBank(OPNMIDIplay::fileReader &fr) } } - opn.dynamic_instruments.clear(); - opn.dynamic_metainstruments.clear(); - if((readU16BE(fr, count_melodic_banks) != 2) || (readU16BE(fr, count_percusive_banks) != 2)) + opn.cleanInstrumentBanks(); + if((readU16BE(fr, count_melodic_banks) != 2) || (readU16BE(fr, count_percussive_banks) != 2)) { errorStringOut = "Can't load bank file: Can't read count of banks!"; return false; } - if((count_melodic_banks < 1) || (count_percusive_banks < 1)) + if((count_melodic_banks < 1) || (count_percussive_banks < 1)) { errorStringOut = "Custom bank: Too few banks in this file!"; return false; @@ -214,8 +213,10 @@ bool OPNMIDIplay::LoadBank(OPNMIDIplay::fileReader &fr) return false; } - opn.dynamic_melodic_banks.clear(); - opn.dynamic_percussion_banks.clear(); + opn.cleanInstrumentBanks(); + + std::vector banks; + banks.reserve(count_melodic_banks + count_percussive_banks); if(version >= 2)//Read bank meta-entries { @@ -224,49 +225,44 @@ bool OPNMIDIplay::LoadBank(OPNMIDIplay::fileReader &fr) uint8_t bank_meta[34]; if(fr.read(bank_meta, 1, 34) != 34) { - opn.dynamic_melodic_banks.clear(); + opn.cleanInstrumentBanks(); errorStringOut = "Custom bank: Fail to read melodic bank meta-data!"; return false; } - uint16_t bank = uint16_t(bank_meta[33]) * 256 + uint16_t(bank_meta[32]); - size_t offset = opn.dynamic_melodic_banks.size(); - opn.dynamic_melodic_banks[bank] = offset; - //strncpy(bankMeta.name, char_p(bank_meta), 32); + uint16_t bankno = uint16_t(bank_meta[33]) * 256 + uint16_t(bank_meta[32]); + OPN2::Bank &bank = opn.dynamic_banks[bankno]; + //strncpy(bank.name, char_p(bank_meta), 32); + banks.push_back(&bank); } - for(uint16_t i = 0; i < count_percusive_banks; i++) + for(uint16_t i = 0; i < count_percussive_banks; i++) { uint8_t bank_meta[34]; if(fr.read(bank_meta, 1, 34) != 34) { - opn.dynamic_melodic_banks.clear(); - opn.dynamic_percussion_banks.clear(); + opn.cleanInstrumentBanks(); errorStringOut = "Custom bank: Fail to read percussion bank meta-data!"; return false; } - uint16_t bank = uint16_t(bank_meta[33]) * 256 + uint16_t(bank_meta[32]); - size_t offset = opn.dynamic_percussion_banks.size(); - opn.dynamic_percussion_banks[bank] = offset; - //strncpy(bankMeta.name, char_p(bank_meta), 32); + uint16_t bankno = uint16_t(bank_meta[33]) * 256 + uint16_t(bank_meta[32]) + OPN2::PercussionTag; + OPN2::Bank &bank = opn.dynamic_banks[bankno]; + //strncpy(bank.name, char_p(bank_meta), 32); + banks.push_back(&bank); } } - opn.dynamic_percussion_offset = count_melodic_banks * 128; - uint16_t total = 128 * count_melodic_banks + 128 * count_percusive_banks; + size_t total = 128 * opn.dynamic_banks.size(); - for(uint16_t i = 0; i < total; i++) + for(size_t i = 0; i < total; i++) { - opnInstData data; - opnInstMeta meta; + opnInstMeta2 &meta = banks[i / 128]->ins[i % 128]; + opnInstData &data = meta.opn[0]; uint8_t idata[WOPL_INST_SIZE_V2]; size_t readSize = version >= 2 ? WOPL_INST_SIZE_V2 : WOPL_INST_SIZE_V1; if(fr.read(idata, 1, readSize) != readSize) { - opn.dynamic_instruments.clear(); - opn.dynamic_metainstruments.clear(); - opn.dynamic_melodic_banks.clear(); - opn.dynamic_percussion_banks.clear(); + opn.cleanInstrumentBanks(); errorStringOut = "Can't load bank file: Failed to read instrument data"; return false; } @@ -295,15 +291,11 @@ bool OPNMIDIplay::LoadBank(OPNMIDIplay::fileReader &fr) meta.ms_sound_koff = 500; } - meta.opnno1 = uint16_t(opn.dynamic_instruments.size()); - meta.opnno2 = uint16_t(opn.dynamic_instruments.size()); + meta.opn[1] = meta.opn[0]; /* Junk, delete later */ meta.fine_tune = 0.0; /* Junk, delete later */ - - opn.dynamic_instruments.push_back(data); - opn.dynamic_metainstruments.push_back(meta); } applySetup(); @@ -336,7 +328,7 @@ bool OPNMIDIplay::LoadMIDI(OPNMIDIplay::fileReader &fr) AdlMIDI_CPtr cvt_buf; errorString.clear(); - if(opn.dynamic_instruments.empty()) + if(opn.dynamic_banks.empty()) { errorStringOut = "Bank is not set! Please load any instruments bank by using of adl_openBankFile() or adl_openBankData() functions!"; return false; @@ -470,7 +462,6 @@ riffskip: fr.seek(0x7D, SEEK_SET); TrackCount = 1; DeltaTicks = 60; - opn.LogarithmicVolumes = true; //opl.CartoonersVolumes = true; opn.m_musicMode = OPN2::MODE_RSXX; opn.m_volumeScale = OPN2::VOLUME_CMF; @@ -494,11 +485,8 @@ riffskip: TrackData.clear(); TrackData.resize(TrackCount, std::vector()); - //CurrentPosition.track.clear(); - //CurrentPosition.track.resize(TrackCount); InvDeltaTicks = fraction(1, 1000000l * static_cast(DeltaTicks)); - //Tempo = 1000000l * InvDeltaTicks; - Tempo = fraction(1, static_cast(DeltaTicks)); + Tempo = fraction(1, static_cast(DeltaTicks) * 2); static const unsigned char EndTag[4] = {0xFF, 0x2F, 0x00, 0x00}; size_t totalGotten = 0; @@ -560,14 +548,14 @@ riffskip: return false; } - //Build new MIDI events table (ALPHA!!!) + //Build new MIDI events table if(!buildTrackData()) { errorStringOut = fr._fileName + ": MIDI data parsing error has occouped!\n" + errorString; return false; } - opn.Reset(m_setup.PCM_RATE); // Reset AdLib + opn.Reset(m_setup.emulator, m_setup.PCM_RATE); // Reset OPN2 chip ch.clear(); ch.resize(opn.NumChannels); return true; diff --git a/src/sound/opnmidi/opnmidi_midiplay.cpp b/src/sound/opnmidi/opnmidi_midiplay.cpp index cd77429d8..5a93bb36e 100644 --- a/src/sound/opnmidi/opnmidi_midiplay.cpp +++ b/src/sound/opnmidi/opnmidi_midiplay.cpp @@ -77,18 +77,19 @@ inline bool isXgPercChannel(uint8_t msb, uint8_t lsb) void OPNMIDIplay::OpnChannel::AddAge(int64_t ms) { - if(users.empty()) + const int64_t neg = static_cast(-0x1FFFFFFFl); + if(users_empty()) koff_time_until_neglible = - std::max(int64_t(koff_time_until_neglible - ms), static_cast(-0x1FFFFFFFl)); + std::max(int64_t(koff_time_until_neglible - ms), neg); else { koff_time_until_neglible = 0; - for(users_t::iterator i = users.begin(); i != users.end(); ++i) + for(LocationData *i = users_first; i; i = i->next) { - i->second.kon_time_until_neglible = - std::max(i->second.kon_time_until_neglible - ms, static_cast(-0x1FFFFFFFl)); - i->second.vibdelay += ms; + if(!i->fixed_sustain) + i->kon_time_until_neglible = std::max(i->kon_time_until_neglible - ms, neg); + i->vibdelay += ms; } } } @@ -655,9 +656,10 @@ bool OPNMIDIplay::buildTrackData() #endif //OPNMIDI_DISABLE_MIDI_SEQUENCER -OPNMIDIplay::OPNMIDIplay(unsigned long sampleRate) +OPNMIDIplay::OPNMIDIplay(unsigned long sampleRate) : + m_arpeggioCounter(0) #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER - : fullSongTimeLength(0.0), + , fullSongTimeLength(0.0), postSongWaitDelay(1.0), loopStartTime(-1.0), loopEndTime(-1.0), @@ -670,6 +672,9 @@ OPNMIDIplay::OPNMIDIplay(unsigned long sampleRate) { devices.clear(); + m_setup.emulator = OPNMIDI_EMU_MAME; + m_setup.runAtPcmRate = false; + m_setup.PCM_RATE = sampleRate; m_setup.mindelay = 1.0 / (double)m_setup.PCM_RATE; m_setup.maxdelay = 512.0 / (double)m_setup.PCM_RATE; @@ -681,6 +686,7 @@ OPNMIDIplay::OPNMIDIplay(unsigned long sampleRate) //m_setup.SkipForward = 0; m_setup.loopingIsEnabled = false; m_setup.ScaleModulators = 0; + m_setup.fullRangeBrightnessCC74 = false; m_setup.delay = 0.0; m_setup.carry = 0.0; m_setup.tick_skip_samples_delay = 0; @@ -694,18 +700,24 @@ void OPNMIDIplay::applySetup() { m_setup.tick_skip_samples_delay = 0; - opn.ScaleModulators = m_setup.ScaleModulators; - opn.LogarithmicVolumes = m_setup.LogarithmicVolumes; + opn.ScaleModulators = (m_setup.ScaleModulators != 0); + opn.runAtPcmRate = m_setup.runAtPcmRate; opn.m_musicMode = OPN2::MODE_MIDI; - opn.ChangeVolumeRangesModel(static_cast(m_setup.VolumeModel)); + if(m_setup.LogarithmicVolumes != 0) + opn.ChangeVolumeRangesModel(OPNMIDI_VolumeModel_CMF); + else + opn.ChangeVolumeRangesModel(static_cast(m_setup.VolumeModel)); if(m_setup.VolumeModel == OPNMIDI_VolumeModel_AUTO) opn.m_volumeScale = OPN2::VOLUME_Generic; opn.NumCards = m_setup.NumCards; - opn.Reset(m_setup.PCM_RATE); + opn.Reset(m_setup.emulator, m_setup.PCM_RATE); ch.clear(); - ch.resize(opn.NumChannels); + ch.resize(opn.NumChannels, OpnChannel()); + + // Reset the arpeggio counter + m_arpeggioCounter = 0; } uint64_t OPNMIDIplay::ReadVarLen(uint8_t **ptr) @@ -898,20 +910,12 @@ void OPNMIDIplay::realTime_ResetState() for(size_t ch = 0; ch < Ch.size(); ch++) { MIDIchannel &chan = Ch[ch]; + chan.resetAllControllers(); chan.volume = (opn.m_musicMode == OPN2::MODE_RSXX) ? 127 : 100; - chan.expression = 127; - chan.panning = 0xC0; - chan.vibrato = 0; - chan.sustain = 0; - chan.bend = 0.0; - chan.bendsense = 2 / 8192.0; chan.vibpos = 0.0; - chan.vibdepth = 0.5 / 127.0; - chan.vibdelay = 0; chan.lastlrpn = 0; chan.lastmrpn = 0; chan.nrpn = false; - chan.brightness = 127; NoteUpdate_All(uint16_t(ch), Upd_All); NoteUpdate_All(uint16_t(ch), Upd_Off); } @@ -919,13 +923,16 @@ void OPNMIDIplay::realTime_ResetState() bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) { + if(note >= 127) + note = 127; + if((opn.m_musicMode == OPN2::MODE_RSXX) && (velocity != 0)) { // Check if this is just a note after-touch - MIDIchannel::activenoteiterator i = Ch[channel].activenotes.find(note); - if(i != Ch[channel].activenotes.end()) + MIDIchannel::activenoteiterator i = Ch[channel].activenotes_find(note); + if(i) { - i->second.vol = velocity; + i->vol = velocity; NoteUpdate(channel, i, Upd_Volume); return false; } @@ -941,14 +948,16 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit if(velocity == 0) return false; - size_t midiins = Ch[channel].patch; + MIDIchannel &midiChan = Ch[channel]; + + size_t midiins = midiChan.patch; bool isPercussion = (channel % 16 == 9); bool isXgPercussion = false; uint16_t bank = 0; - if(Ch[channel].bank_msb || Ch[channel].bank_lsb) + if(midiChan.bank_msb || midiChan.bank_lsb) { - bank = (uint16_t(Ch[channel].bank_msb) * 256) + uint16_t(Ch[channel].bank_lsb); + bank = (uint16_t(midiChan.bank_msb) * 256) + uint16_t(midiChan.bank_lsb); //0x7E00 - XG SFX1/SFX2 channel (16128 signed decimal) //0x7F00 - XG Percussion channel (16256 signed decimal) if(bank == 0x7E00 || bank == 0x7F00) @@ -956,7 +965,7 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit //Let XG SFX1/SFX2 bank will have LSB==1 (128...255 range in WOPN file) //Let XG Percussion bank will use (0...127 range in WOPN file) bank = (uint16_t)midiins + ((bank == 0x7E00) ? 128 : 0); // MIDI instrument defines the patch - midiins = opn.dynamic_percussion_offset + note; // Percussion instrument + midiins = note; // Percussion instrument isXgPercussion = true; isPercussion = false; } @@ -965,43 +974,43 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit if(isPercussion) { bank = (uint16_t)midiins; // MIDI instrument defines the patch - midiins = opn.dynamic_percussion_offset + note; // Percussion instrument + midiins = note; // Percussion instrument } + if(isPercussion || isXgPercussion) + bank += OPN2::PercussionTag; + + const opnInstMeta2 *ains = &OPN2::emptyInstrument; //Set bank bank - if(bank > 0) + const OPN2::Bank *bnk = NULL; + if((bank & ~(uint16_t)OPN2::PercussionTag) > 0) { - if(isPercussion || isXgPercussion) + OPN2::BankMap::iterator b = opn.dynamic_banks.find(bank); + if(b != opn.dynamic_banks.end()) + bnk = &b->second; + + if(bnk) + ains = &bnk->ins[midiins]; + else if(hooks.onDebugMessage) { - OPN2::BankMap::iterator b = opn.dynamic_percussion_banks.find(bank); - if(b != opn.dynamic_percussion_banks.end()) - midiins += b->second * 128; - else - if(hooks.onDebugMessage) - { - if(!caugh_missing_banks_melodic.count(bank)) - { - hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing percussion MIDI bank %i (patch %i)", channel, bank, midiins); - caugh_missing_banks_melodic.insert(bank); - } - } - } - else - { - OPN2::BankMap::iterator b = opn.dynamic_melodic_banks.find(bank); - if(b != opn.dynamic_melodic_banks.end()) - midiins += b->second * 128; - else - if(hooks.onDebugMessage) - { - if(!caugh_missing_banks_melodic.count(bank)) - { - hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing melodic MIDI bank %i (patch %i)", channel, bank, midiins); - caugh_missing_banks_melodic.insert(bank); - } - } + std::set &missing = (isPercussion || isXgPercussion) ? + caugh_missing_banks_percussion : caugh_missing_banks_melodic; + const char *text = (isPercussion || isXgPercussion) ? + "percussion" : "melodic"; + if(missing.insert(bank).second) + hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Playing missing %s MIDI bank %i (patch %i)", channel, text, bank, midiins); } } + //Or fall back to first bank + if(ains->flags & opnInstMeta::Flag_NoSound) + { + OPN2::BankMap::iterator b = opn.dynamic_banks.find(bank & OPN2::PercussionTag); + if(b != opn.dynamic_banks.end()) + bnk = &b->second; + + if(bnk) + ains = &bnk->ins[midiins]; + } /* if(MidCh%16 == 9 || (midiins != 32 && midiins != 46 && midiins != 48 && midiins != 50)) @@ -1011,8 +1020,6 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit */ //if(midiins == 56) vol = vol*6/10; // HACK - size_t meta = opn.GetAdlMetaNumber(midiins); - const opnInstMeta *ains = &opn.GetAdlMetaIns(meta); int16_t tone = note; if(!isPercussion && !isXgPercussion && (bank > 0)) // For non-zero banks @@ -1023,14 +1030,12 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit { if(!caugh_missing_instruments.count(static_cast(midiins))) { - hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Caugh a blank instrument %i (offset %i) in the MIDI bank %u", channel, Ch[channel].patch, midiins, bank); + hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Caugh a blank instrument %i (offset %i) in the MIDI bank %u", channel, midiChan.patch, midiins, bank); caugh_missing_instruments.insert(static_cast(midiins)); } } bank = 0; - midiins = Ch[channel].patch; - meta = opn.GetAdlMetaNumber(midiins); - ains = &opn.GetAdlMetaIns(meta); + midiins = midiChan.patch; } } @@ -1045,7 +1050,10 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit tone -= ains->tone - 128; } - uint16_t i[2] = { ains->opnno1, ains->opnno2 }; + MIDIchannel::NoteInfo::Phys voices[MIDIchannel::NoteInfo::MaxNumPhysChans] = { + {0, ains->opn[0], /*false*/}, + {0, ains->opn[1], /*pseudo_4op*/}, + }; //bool pseudo_4op = ains.flags & opnInstMeta::Flag_Pseudo8op; //if((opn.AdlPercussionMode == 1) && PercussionMap[midiins & 0xFF]) i[1] = i[0]; @@ -1059,13 +1067,13 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit } // Allocate AdLib channel (the physical sound channel for the note) - int32_t adlchannel[2] = { -1, -1 }; + int32_t adlchannel[MIDIchannel::NoteInfo::MaxNumPhysChans] = { -1, -1 }; - for(uint32_t ccount = 0; ccount < 2; ++ccount) + for(uint32_t ccount = 0; ccount < MIDIchannel::NoteInfo::MaxNumPhysChans; ++ccount) { if(ccount == 1) { - if(i[0] == i[1]) + if(voices[0] == voices[1]) break; // No secondary channel if(adlchannel[0] == -1) break; // No secondary if primary failed @@ -1079,7 +1087,7 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit if(ccount == 1 && static_cast(a) == adlchannel[0]) continue; // ^ Don't use the same channel for primary&secondary // ===== Kept for future pseudo-8-op mode - //if(i[0] == i[1] || pseudo_4op) + //if(voices[0] == voices[1] || pseudo_4op) //{ // // Only use regular channels // uint8_t expected_mode = 0; @@ -1093,7 +1101,7 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit // if(opn.four_op_category[a] != expected_mode) // continue; //} - int64_t s = CalculateAdlChannelGoodness(a, i[ccount], channel); + int64_t s = CalculateAdlChannelGoodness(a, voices[ccount], channel); if(s > bs) { bs = (int32_t)s; // Best candidate wins @@ -1106,11 +1114,11 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit if(hooks.onDebugMessage) hooks.onDebugMessage(hooks.onDebugMessage_userData, "ignored unplaceable note [bank %i, inst %i, note %i, MIDI channel %i]", - bank, Ch[channel].patch, note, channel); + bank, midiChan.patch, note, channel); continue; // Could not play this note. Ignore it. } - PrepareAdlChannelForNewNote(static_cast(c), i[ccount]); + PrepareAdlChannelForNewNote(static_cast(c), voices[ccount]); adlchannel[ccount] = c; } @@ -1125,19 +1133,21 @@ bool OPNMIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocit // Allocate active note for MIDI channel std::pair - ir = Ch[channel].activenotes.insert(std::make_pair(note, MIDIchannel::NoteInfo())); - ir.first->second.vol = velocity; - ir.first->second.tone = tone; - ir.first->second.midiins = midiins; - ir.first->second.insmeta = meta; + ir = midiChan.activenotes_insert(note); + ir.first->vol = velocity; + ir.first->vibrato = midiChan.noteAftertouch[note]; + ir.first->tone = tone; + ir.first->midiins = midiins; + ir.first->ains = ains; + ir.first->chip_channels_count = 0; - for(unsigned ccount = 0; ccount < 2; ++ccount) + for(unsigned ccount = 0; ccount < MIDIchannel::NoteInfo::MaxNumPhysChans; ++ccount) { int32_t c = adlchannel[ccount]; if(c < 0) continue; uint16_t chipChan = static_cast(adlchannel[ccount]); - ir.first->second.phys[chipChan] = i[ccount]; + ir.first->phys_ensure_find_or_create(chipChan)->assign(voices[ccount]); } NoteUpdate(channel, ir.first, Upd_All | Upd_Patch); return true; @@ -1152,31 +1162,28 @@ void OPNMIDIplay::realTime_NoteOff(uint8_t channel, uint8_t note) void OPNMIDIplay::realTime_NoteAfterTouch(uint8_t channel, uint8_t note, uint8_t atVal) { channel = channel % 16; - MIDIchannel::activenoteiterator - i = Ch[channel].activenotes.find(note); - if(i == Ch[channel].activenotes.end()) + MIDIchannel &chan = Ch[channel]; + MIDIchannel::activenoteiterator i = Ch[channel].activenotes_find(note); + if(i) { - // Ignore touch if note is not active - return; + i->vibrato = atVal; + } + + uint8_t oldAtVal = chan.noteAftertouch[note % 128]; + if(atVal != oldAtVal) + { + chan.noteAftertouch[note % 128] = atVal; + bool inUse = atVal != 0; + for(unsigned n = 0; !inUse && n < 128; ++n) + inUse = chan.noteAftertouch[n] != 0; + chan.noteAfterTouchInUse = inUse; } - i->second.vol = 127 - atVal; - NoteUpdate(channel, i, Upd_Volume); } void OPNMIDIplay::realTime_ChannelAfterTouch(uint8_t channel, uint8_t atVal) { - // TODO: Verify, is this correct action? channel = channel % 16; - for(MIDIchannel::activenoteiterator - i = Ch[channel].activenotes.begin(); - i != Ch[channel].activenotes.end(); - ++i) - { - // Set this pressure to all active notes on the channel - i->second.vol = 127 - atVal; - } - - NoteUpdate_All(channel, Upd_Volume); + Ch[channel].aftertouch = atVal; } void OPNMIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value) @@ -1236,29 +1243,23 @@ void OPNMIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t val case 10: // Change panning Ch[channel].panning = 0x00; - if(value < 64 + 32) Ch[channel].panning |= 0x80; - if(value >= 64 - 32) Ch[channel].panning |= 0x40; + if(value < 64 + 32) Ch[channel].panning |= OPN_PANNING_LEFT; + if(value >= 64 - 32) Ch[channel].panning |= OPN_PANNING_RIGHT; NoteUpdate_All(channel, Upd_Pan); break; case 121: // Reset all controllers - Ch[channel].bend = 0; - Ch[channel].volume = 100; - Ch[channel].expression = 127; - Ch[channel].sustain = 0; - Ch[channel].vibrato = 0; - Ch[channel].vibspeed = 2 * 3.141592653 * 5.0; - Ch[channel].vibdepth = 0.5 / 127; - Ch[channel].vibdelay = 0; - Ch[channel].panning = 0xC0; - Ch[channel].portamento = 0; - Ch[channel].brightness = 127; + Ch[channel].resetAllControllers(); //UpdatePortamento(MidCh); NoteUpdate_All(channel, Upd_Pan + Upd_Volume + Upd_Pitch); // Kill all sustained notes KillSustainingNotes(channel); break; + case 120: // All sounds off + NoteUpdate_All(channel, Upd_OffMute); + break; + case 123: // All notes off NoteUpdate_All(channel, Upd_Off); break; @@ -1328,14 +1329,14 @@ void OPNMIDIplay::realTime_PatchChange(uint8_t channel, uint8_t patch) void OPNMIDIplay::realTime_PitchBend(uint8_t channel, uint16_t pitch) { channel = channel % 16; - Ch[channel].bend = (uint32_t(pitch) - 8192) * Ch[channel].bendsense; + Ch[channel].bend = int(pitch) - 8192; NoteUpdate_All(channel, Upd_Pitch); } void OPNMIDIplay::realTime_PitchBend(uint8_t channel, uint8_t msb, uint8_t lsb) { channel = channel % 16; - Ch[channel].bend = (int(lsb) + int(msb) * 128 - 8192) * Ch[channel].bendsense; + Ch[channel].bend = int(lsb) + int(msb) * 128 - 8192; NoteUpdate_All(channel, Upd_Pitch); } @@ -1370,79 +1371,81 @@ void OPNMIDIplay::NoteUpdate(uint16_t MidCh, unsigned props_mask, int32_t select_adlchn) { - MIDIchannel::NoteInfo &info = i->second; + MIDIchannel::NoteInfo &info = *i; const int16_t tone = info.tone; const uint8_t vol = info.vol; const size_t midiins = info.midiins; - const size_t insmeta = info.insmeta; - const opnInstMeta &ains = opn.GetAdlMetaIns(insmeta); + const opnInstMeta2 &ains = *info.ains; OpnChannel::Location my_loc; my_loc.MidCh = MidCh; - my_loc.note = i->first; + my_loc.note = info.note; - for(MIDIchannel::NoteInfo::PhysMap::iterator - jnext = info.phys.begin(); - jnext != info.phys.end(); - ) + for(unsigned ccount = 0, ctotal = info.chip_channels_count; ccount < ctotal; ccount++) { - MIDIchannel::NoteInfo::PhysMap::iterator j(jnext++); - uint16_t c = j->first; - const MIDIchannel::NoteInfo::Phys &ins = j->second; + const MIDIchannel::NoteInfo::Phys &ins = info.chip_channels[ccount]; + uint16_t c = ins.chip_chan; if(select_adlchn >= 0 && c != select_adlchn) continue; if(props_mask & Upd_Patch) { - opn.Patch(c, ins); - OpnChannel::LocationData &d = ch[c].users[my_loc]; - d.sustained = false; // inserts if necessary - d.vibdelay = 0; - d.kon_time_until_neglible = ains.ms_sound_kon; - d.ins = ins; + opn.Patch(c, ins.ains); + OpnChannel::LocationData *d = ch[c].users_find_or_create(my_loc); + if(d) { // inserts if necessary + d->sustained = false; + d->vibdelay = 0; + d->fixed_sustain = (ains.ms_sound_kon == static_cast(opnNoteOnMaxTime)); + d->kon_time_until_neglible = ains.ms_sound_kon; + d->ins = ins; + } } } - for(MIDIchannel::NoteInfo::PhysMap::iterator - jnext = info.phys.begin(); - jnext != info.phys.end(); - ) + for(unsigned ccount = 0; ccount < info.chip_channels_count; ccount++) { - MIDIchannel::NoteInfo::PhysMap::iterator j(jnext++); - uint16_t c = j->first; - const MIDIchannel::NoteInfo::Phys &ins = j->second; + const MIDIchannel::NoteInfo::Phys &ins = info.chip_channels[ccount]; + uint16_t c = ins.chip_chan; - if(select_adlchn >= 0 && c != select_adlchn) continue; + if(select_adlchn >= 0 && c != select_adlchn) + continue; if(props_mask & Upd_Off) // note off { if(Ch[MidCh].sustain == 0) { - OpnChannel::users_t::iterator k = ch[c].users.find(my_loc); + OpnChannel::LocationData *k = ch[c].users_find(my_loc); - if(k != ch[c].users.end()) - ch[c].users.erase(k); + if(k) + ch[c].users_erase(k); if(hooks.onNote) hooks.onNote(hooks.onNote_userData, c, tone, (int)midiins, 0, 0.0); - if(ch[c].users.empty()) + if(ch[c].users_empty()) { opn.NoteOff(c); - ch[c].koff_time_until_neglible = - ains.ms_sound_koff; + if(props_mask & Upd_Mute) // Mute the note + { + opn.Touch_Real(c, 0); + ch[c].koff_time_until_neglible = 0; + } else { + ch[c].koff_time_until_neglible = ains.ms_sound_koff; + } } } else { // Sustain: Forget about the note, but don't key it off. // Also will avoid overwriting it very soon. - OpnChannel::LocationData &d = ch[c].users[my_loc]; - d.sustained = true; // note: not erased! + OpnChannel::LocationData *d = ch[c].users_find_or_create(my_loc); + if(d) + d->sustained = true; // note: not erased! if(hooks.onNote) hooks.onNote(hooks.onNote_userData, c, tone, (int)midiins, -1, 0.0); } - info.phys.erase(j); + info.phys_erase_at(&ins); // decrements channel count + --ccount; // adjusts index accordingly continue; } @@ -1455,13 +1458,20 @@ void OPNMIDIplay::NoteUpdate(uint16_t MidCh, bool is_percussion = (MidCh == 9) || Ch[MidCh].is_xg_percussion; uint8_t brightness = is_percussion ? 127 : Ch[MidCh].brightness; + if(!m_setup.fullRangeBrightnessCC74) + { + // Simulate post-High-Pass filter result which affects sounding by half level only + if(brightness >= 64) + brightness = 127; + else + brightness *= 2; + } + switch(opn.m_volumeScale) { case OPN2::VOLUME_Generic: - case OPN2::VOLUME_CMF: { volume = vol * Ch[MidCh].volume * Ch[MidCh].expression; - /* If the channel has arpeggio, the effective volume of * *this* instrument is actually lower due to timesharing. * To compensate, add extra volume that corresponds to the @@ -1471,18 +1481,20 @@ void OPNMIDIplay::NoteUpdate(uint16_t MidCh, */ //volume = (int)(volume * std::sqrt( (double) ch[c].users.size() )); - if(opn.LogarithmicVolumes) - volume = volume * 127 / (2048383/*127 * 127 * 127*/); - else - { - // The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A) - volume = volume > 8725 ? static_cast((std::log(static_cast(volume)) * (11.541561) + (0.5 - 104.22845)) * 2.0) : 0; - // The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A) - //opl.Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0); - } + // The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A) + volume = volume > 8725 ? static_cast((std::log(static_cast(volume)) * (11.541561) + (0.5 - 104.22845)) * 2.0) : 0; + // The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A) + //opl.Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0); opn.Touch_Real(c, volume, brightness); - //opl.Touch(c, volume); + } + break; + + case OPN2::VOLUME_CMF: + { + volume = vol * Ch[MidCh].volume * Ch[MidCh].expression; + volume = volume * 127 / (2048383/*127 * 127 * 127*/); + opn.Touch_Real(c, volume, brightness); } break; @@ -1532,33 +1544,36 @@ void OPNMIDIplay::NoteUpdate(uint16_t MidCh, if(props_mask & Upd_Pitch) { - OpnChannel::LocationData &d = ch[c].users[my_loc]; + OpnChannel::LocationData *d = ch[c].users_find(my_loc); // Don't bend a sustained note - if(!d.sustained) + if(!d || !d->sustained) { - double bend = Ch[MidCh].bend + opn.GetAdlIns(ins).finetune; + double midibend = Ch[MidCh].bend * Ch[MidCh].bendsense; + double bend = midibend + ins.ains.finetune; double phase = 0.0; + uint8_t vibrato = std::max(Ch[MidCh].vibrato, Ch[MidCh].aftertouch); + vibrato = std::max(vibrato, i->vibrato); - if((ains.flags & opnInstMeta::Flag_Pseudo8op) && ins == ains.opnno2) + if((ains.flags & opnInstMeta::Flag_Pseudo8op) && ins.ains == ains.opn[1]) { phase = ains.fine_tune;//0.125; // Detune the note slightly (this is what Doom does) } - if(Ch[MidCh].vibrato && d.vibdelay >= Ch[MidCh].vibdelay) - bend += Ch[MidCh].vibrato * Ch[MidCh].vibdepth * std::sin(Ch[MidCh].vibpos); + if(vibrato && (!d || d->vibdelay >= Ch[MidCh].vibdelay)) + bend += static_cast(vibrato) * Ch[MidCh].vibdepth * std::sin(Ch[MidCh].vibpos); #define BEND_COEFFICIENT 321.88557 - opn.NoteOn(c, BEND_COEFFICIENT * std::exp(0.057762265 * (tone + bend + phase))); + opn.NoteOn(c, BEND_COEFFICIENT * std::exp(0.057762265 * (static_cast(tone) + bend + phase))); #undef BEND_COEFFICIENT if(hooks.onNote) - hooks.onNote(hooks.onNote_userData, c, tone, (int)midiins, vol, Ch[MidCh].bend); + hooks.onNote(hooks.onNote_userData, c, tone, (int)midiins, vol, midibend); } } } - if(info.phys.empty()) - Ch[MidCh].activenotes.erase(i); + if(info.chip_channels_count == 0) + Ch[MidCh].activenotes_erase(i); } #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER @@ -1723,6 +1738,14 @@ OPNMIDIplay::MidiEvent OPNMIDIplay::parseEvent(uint8_t **pptr, uint8_t *end, int evt.subtype = evtype; evt.data.insert(evt.data.begin(), data.begin(), data.end()); +#if 0 /* Print all tempo events */ + if(evt.subtype == MidiEvent::ST_TEMPOCHANGE) + { + if(hooks.onDebugMessage) + hooks.onDebugMessage(hooks.onDebugMessage_userData, "Temp Change: %02X%02X%02X", evt.data[0], evt.data[1], evt.data[2]); + } +#endif + /* TODO: Store those meta-strings separately and give ability to read them * by external functions (to display song title and copyright in the player) */ if(evt.subtype == MidiEvent::ST_COPYRIGHT) @@ -2050,41 +2073,38 @@ void OPNMIDIplay::HandleEvent(size_t tk, const OPNMIDIplay::MidiEvent &evt, int } #endif //OPNMIDI_DISABLE_MIDI_SEQUENCER -int64_t OPNMIDIplay::CalculateAdlChannelGoodness(size_t c, uint16_t ins, uint16_t) const +int64_t OPNMIDIplay::CalculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t) const { int64_t s = -ch[c].koff_time_until_neglible; // Same midi-instrument = some stability //if(c == MidCh) s += 4; - for(OpnChannel::users_t::const_iterator - j = ch[c].users.begin(); - j != ch[c].users.end(); - ++j) + for (OpnChannel::LocationData *j = ch[c].users_first; j; j = j->next) { s -= 4000; - if(!j->second.sustained) - s -= j->second.kon_time_until_neglible; + if(!j->sustained) + s -= j->kon_time_until_neglible; else - s -= (j->second.kon_time_until_neglible / 2); + s -= (j->kon_time_until_neglible / 2); - MIDIchannel::activenotemap_t::const_iterator - k = Ch[j->first.MidCh].activenotes.find(j->first.note); + MIDIchannel::activenoteiterator + k = const_cast(Ch[j->loc.MidCh]).activenotes_find(j->loc.note); - if(k != Ch[j->first.MidCh].activenotes.end()) + if(k) { // Same instrument = good - if(j->second.ins == ins) + if(j->ins == ins) { s += 300; // Arpeggio candidate = even better - if(j->second.vibdelay < 70 - || j->second.kon_time_until_neglible > 20000) + if(j->vibdelay < 70 + || j->kon_time_until_neglible > 20000) s += 0; } // Percussion is inferior to melody - s += 50 * (int64_t)(k->second.midiins / 128); + s += 50 * (int64_t)(k->midiins / 128); /* if(k->second.midiins >= 25 && k->second.midiins < 40 @@ -2107,14 +2127,11 @@ int64_t OPNMIDIplay::CalculateAdlChannelGoodness(size_t c, uint16_t ins, uint16_ // if(opn.four_op_category[c2] // != opn.four_op_category[c]) continue; -// for(OpnChannel::users_t::const_iterator -// m = ch[c2].users.begin(); -// m != ch[c2].users.end(); -// ++m) +// for(OpnChannel::LocationData *m = ch[c2].users_first; m; m = m->next) // { -// if(m->second.sustained) continue; -// if(m->second.vibdelay >= 200) continue; -// if(m->second.ins != j->second.ins) continue; +// if(m->sustained) continue; +// if(m->vibdelay >= 200) continue; +// if(m->ins != j->second.ins) continue; // n_evacuation_stations += 1; // } // } @@ -2126,29 +2143,27 @@ int64_t OPNMIDIplay::CalculateAdlChannelGoodness(size_t c, uint16_t ins, uint16_ } -void OPNMIDIplay::PrepareAdlChannelForNewNote(size_t c, size_t ins) +void OPNMIDIplay::PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins) { - if(ch[c].users.empty()) return; // Nothing to do + if(ch[c].users_empty()) return; // Nothing to do //bool doing_arpeggio = false; - for(OpnChannel::users_t::iterator - jnext = ch[c].users.begin(); - jnext != ch[c].users.end(); - ) + for(OpnChannel::LocationData *jnext = ch[c].users_first; jnext;) { - OpnChannel::users_t::iterator j(jnext++); + OpnChannel::LocationData *j = jnext; + jnext = jnext->next; - if(!j->second.sustained) + if(!j->sustained) { // Collision: Kill old note, // UNLESS we're going to do arpeggio MIDIchannel::activenoteiterator i - (Ch[j->first.MidCh].activenotes.find(j->first.note)); + (Ch[j->loc.MidCh].activenotes_ensure_find(j->loc.note)); // Check if we can do arpeggio. - if((j->second.vibdelay < 70 - || j->second.kon_time_until_neglible > 20000) - && j->second.ins == ins) + if((j->vibdelay < 70 + || j->kon_time_until_neglible > 20000) + && j->ins == ins) { // Do arpeggio together with this note. //doing_arpeggio = true; @@ -2167,11 +2182,13 @@ void OPNMIDIplay::PrepareAdlChannelForNewNote(size_t c, size_t ins) // Keyoff the channel so that it can be retriggered, // unless the new note will be introduced as just an arpeggio. - if(ch[c].users.empty()) + if(ch[c].users_empty()) opn.NoteOff(c); } -void OPNMIDIplay::KillOrEvacuate(size_t from_channel, OpnChannel::users_t::iterator j, OPNMIDIplay::MIDIchannel::activenoteiterator i) +void OPNMIDIplay::KillOrEvacuate(size_t from_channel, + OpnChannel::LocationData *j, + OPNMIDIplay::MIDIchannel::activenoteiterator i) { // Before killing the note, check if it can be // evacuated to another channel as an arpeggio @@ -2189,32 +2206,34 @@ void OPNMIDIplay::KillOrEvacuate(size_t from_channel, OpnChannel::users_t::itera //if(opn.four_op_category[c] != opn.four_op_category[from_channel]) // continue; - for(OpnChannel::users_t::iterator - m = ch[c].users.begin(); - m != ch[c].users.end(); - ++m) + OpnChannel &adlch = ch[c]; + if(adlch.users_size == OpnChannel::users_max) + continue; // no room for more arpeggio on channel + + for(OpnChannel::LocationData *m = adlch.users_first; m; m = m->next) { - if(m->second.vibdelay >= 200 - && m->second.kon_time_until_neglible < 10000) continue; - if(m->second.ins != j->second.ins) + if(m->vibdelay >= 200 + && m->kon_time_until_neglible < 10000) continue; + if(m->ins != j->ins) continue; if(hooks.onNote) { hooks.onNote(hooks.onNote_userData, (int)from_channel, - i->second.tone, - (int)i->second.midiins, 0, 0.0); + i->tone, + (int)i->midiins, 0, 0.0); hooks.onNote(hooks.onNote_userData, (int)c, - i->second.tone, - (int)i->second.midiins, - i->second.vol, 0.0); + i->tone, + (int)i->midiins, + i->vol, 0.0); } - i->second.phys.erase(static_cast(from_channel)); - i->second.phys[cs] = j->second.ins; - ch[cs].users.insert(*j); - ch[from_channel].users.erase(j); + i->phys_erase(static_cast(from_channel)); + i->phys_ensure_find_or_create(cs)->assign(j->ins); + if(!ch[cs].users_insert(*j)) + assert(false); + ch[from_channel].users_erase(j); return; } } @@ -2227,7 +2246,7 @@ void OPNMIDIplay::KillOrEvacuate(size_t from_channel, OpnChannel::users_t::itera ins );*/ // Kill it - NoteUpdate(j->first.MidCh, + NoteUpdate(j->loc.MidCh, i, Upd_Off, static_cast(from_channel)); @@ -2254,27 +2273,25 @@ void OPNMIDIplay::KillSustainingNotes(int32_t MidCh, int32_t this_adlchn) for(unsigned c = first; c < last; ++c) { - if(ch[c].users.empty()) continue; // Nothing to do + if(ch[c].users_empty()) continue; // Nothing to do - for(OpnChannel::users_t::iterator - jnext = ch[c].users.begin(); - jnext != ch[c].users.end(); - ) + for(OpnChannel::LocationData *jnext = ch[c].users_first; jnext;) { - OpnChannel::users_t::iterator j(jnext++); + OpnChannel::LocationData *j = jnext; + jnext = jnext->next; - if((MidCh < 0 || j->first.MidCh == MidCh) - && j->second.sustained) + if((MidCh < 0 || j->loc.MidCh == MidCh) + && j->sustained) { int midiins = '?'; if(hooks.onNote) - hooks.onNote(hooks.onNote_userData, (int)c, j->first.note, midiins, 0, 0.0); - ch[c].users.erase(j); + hooks.onNote(hooks.onNote_userData, (int)c, j->loc.note, midiins, 0, 0.0); + ch[c].users_erase(j); } } // Keyoff the channel, if there are no users left. - if(ch[c].users.empty()) + if(ch[c].users_empty()) opn.NoteOff(c); } } @@ -2287,7 +2304,12 @@ void OPNMIDIplay::SetRPN(unsigned MidCh, unsigned value, bool MSB) switch(addr + nrpn * 0x10000 + MSB * 0x20000) { case 0x0000 + 0*0x10000 + 1*0x20000: // Pitch-bender sensitivity - Ch[MidCh].bendsense = value / 8192.0; + Ch[MidCh].bendsense_msb = value; + Ch[MidCh].updateBendSensitivity(); + break; + case 0x0000 + 0*0x10000 + 0*0x20000: // Pitch-bender sensitivity LSB + Ch[MidCh].bendsense_lsb = value; + Ch[MidCh].updateBendSensitivity(); break; case 0x0108 + 1*0x10000 + 1*0x20000: // Vibrato speed if(value == 64) Ch[MidCh].vibspeed = 1.0; @@ -2320,9 +2342,7 @@ void OPNMIDIplay::SetRPN(unsigned MidCh, unsigned value, bool MSB) void OPNMIDIplay::NoteUpdate_All(uint16_t MidCh, unsigned props_mask) { for(MIDIchannel::activenoteiterator - i = Ch[MidCh].activenotes.begin(); - i != Ch[MidCh].activenotes.end(); - ) + i = Ch[MidCh].activenotes_begin(); i;) { MIDIchannel::activenoteiterator j(i++); NoteUpdate(MidCh, j, props_mask); @@ -2332,9 +2352,9 @@ void OPNMIDIplay::NoteUpdate_All(uint16_t MidCh, unsigned props_mask) void OPNMIDIplay::NoteOff(uint16_t MidCh, uint8_t note) { MIDIchannel::activenoteiterator - i = Ch[MidCh].activenotes.find(note); + i = Ch[MidCh].activenotes_find(note); - if(i != Ch[MidCh].activenotes.end()) + if(i) NoteUpdate(MidCh, i, Upd_Off); } @@ -2343,7 +2363,7 @@ void OPNMIDIplay::UpdateVibrato(double amount) { for(size_t a = 0, b = Ch.size(); a < b; ++a) { - if(Ch[a].vibrato && !Ch[a].activenotes.empty()) + if(Ch[a].hasVibrato() && !Ch[a].activenotes_empty()) { NoteUpdate_All(static_cast(a), Upd_Pitch); Ch[a].vibpos += amount * Ch[a].vibspeed; @@ -2392,8 +2412,8 @@ void OPNMIDIplay::UpdateArpeggio(double) // amount = amount of time passed arpeggio_cache = 0.0; #endif #endif - static unsigned arpeggio_counter = 0; - ++arpeggio_counter; + + ++m_arpeggioCounter; for(uint32_t c = 0; c < opn.NumChannels; ++c) { @@ -2401,11 +2421,11 @@ retry_arpeggio: if(c > uint32_t(std::numeric_limits::max())) break; - size_t n_users = ch[c].users.size(); + size_t n_users = ch[c].users_size; if(n_users > 1) { - OpnChannel::users_t::const_iterator i = ch[c].users.begin(); + OpnChannel::LocationData *i = ch[c].users_first; size_t rate_reduction = 3; if(n_users >= 3) @@ -2414,23 +2434,25 @@ retry_arpeggio: if(n_users >= 4) rate_reduction = 1; - std::advance(i, (arpeggio_counter / rate_reduction) % n_users); + for(size_t count = (m_arpeggioCounter / rate_reduction) % n_users, + n = 0; n < count; ++n) + i = i->next; - if(i->second.sustained == false) + if(i->sustained == false) { - if(i->second.kon_time_until_neglible <= 0l) + if(i->kon_time_until_neglible <= 0l) { NoteUpdate( - i->first.MidCh, - Ch[ i->first.MidCh ].activenotes.find(i->first.note), + i->loc.MidCh, + Ch[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note), Upd_Off, static_cast(c)); goto retry_arpeggio; } NoteUpdate( - i->first.MidCh, - Ch[ i->first.MidCh ].activenotes.find(i->first.note), + i->loc.MidCh, + Ch[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note), Upd_Pitch | Upd_Volume | Upd_Pan, static_cast(c)); } @@ -2629,3 +2651,122 @@ retry_arpeggio: //} //#endif//ADLMIDI_DISABLE_CPP_EXTRAS + +// Implement the user map data structure. + +bool OPNMIDIplay::OpnChannel::users_empty() const +{ + return !users_first; +} + +OPNMIDIplay::OpnChannel::LocationData *OPNMIDIplay::OpnChannel::users_find(Location loc) +{ + LocationData *user = NULL; + for(LocationData *curr = users_first; !user && curr; curr = curr->next) + if(curr->loc == loc) + user = curr; + return user; +} + +OPNMIDIplay::OpnChannel::LocationData *OPNMIDIplay::OpnChannel::users_allocate() +{ + // remove free cells front + LocationData *user = users_free_cells; + if(!user) + return NULL; + users_free_cells = user->next; + if(users_free_cells) + users_free_cells->prev = NULL; + // add to users front + if(users_first) + users_first->prev = user; + user->prev = NULL; + user->next = users_first; + users_first = user; + ++users_size; + return user; +} + +OPNMIDIplay::OpnChannel::LocationData *OPNMIDIplay::OpnChannel::users_find_or_create(Location loc) +{ + LocationData *user = users_find(loc); + if(!user) { + user = users_allocate(); + if(!user) + return NULL; + LocationData *prev = user->prev, *next = user->next; + *user = LocationData(); + user->prev = prev; user->next = next; + user->loc = loc; + } + return user; +} + +OPNMIDIplay::OpnChannel::LocationData *OPNMIDIplay::OpnChannel::users_insert(const LocationData &x) +{ + LocationData *user = users_find(x.loc); + if(!user) + { + user = users_allocate(); + if(!user) + return NULL; + LocationData *prev = user->prev, *next = user->next; + *user = x; + user->prev = prev; user->next = next; + } + return user; +} + +void OPNMIDIplay::OpnChannel::users_erase(LocationData *user) +{ + if(user->prev) + user->prev->next = user->next; + if(user->next) + user->next->prev = user->prev; + if(user == users_first) + users_first = user->next; + user->prev = NULL; + user->next = users_free_cells; + users_free_cells = user; + --users_size; +} + +void OPNMIDIplay::OpnChannel::users_clear() +{ + users_first = NULL; + users_free_cells = users_cells; + users_size = 0; + for(size_t i = 0; i < users_max; ++i) + { + users_cells[i].prev = (i > 0) ? &users_cells[i - 1] : NULL; + users_cells[i].next = (i + 1 < users_max) ? &users_cells[i + 1] : NULL; + } +} + +void OPNMIDIplay::OpnChannel::users_assign(const LocationData *users, size_t count) +{ + ADL_UNUSED(count);//Avoid warning for release builds + assert(count <= users_max); + if(users == users_first && users) { + // self assignment + assert(users_size == count); + return; + } + users_clear(); + const LocationData *src_cell = users; + // move to the last + if(src_cell) { + while(src_cell->next) + src_cell = src_cell->next; + } + // push cell copies in reverse order + while(src_cell) { + LocationData *dst_cell = users_allocate(); + assert(dst_cell); + LocationData *prev = dst_cell->prev, *next = dst_cell->next; + *dst_cell = *src_cell; + dst_cell->prev = prev; dst_cell->next = next; + src_cell = src_cell->prev; + } + assert(users_size == count); +} diff --git a/src/sound/opnmidi/opnmidi_opn2.cpp b/src/sound/opnmidi/opnmidi_opn2.cpp index 398ba8980..392294802 100644 --- a/src/sound/opnmidi/opnmidi_opn2.cpp +++ b/src/sound/opnmidi/opnmidi_opn2.cpp @@ -23,6 +23,32 @@ #include "opnmidi_private.hpp" +#if defined(OPNMIDI_DISABLE_NUKED_EMULATOR) && defined(OPNMIDI_DISABLE_MAME_EMULATOR) && \ + defined(OPNMIDI_DISABLE_GENS_EMULATOR) && defined(OPNMIDI_DISABLE_GX_EMULATOR) +#error "No emulators enabled. You must enable at least one emulator to use this library!" +#endif + +// Nuked OPN2 emulator, Most accurate, but requires the powerful CPU +#ifndef OPNMIDI_DISABLE_NUKED_EMULATOR +#include "chips/nuked_opn2.h" +#endif + +// MAME YM2612 emulator, Well-accurate and fast +#ifndef OPNMIDI_DISABLE_MAME_EMULATOR +#include "chips/mame_opn2.h" +#endif + +// GENS 2.10 emulator, very outdated and inaccurate, but gives the best performance +#ifndef OPNMIDI_DISABLE_GENS_EMULATOR +#include "chips/gens_opn2.h" +#endif + +// Genesis Plus GX emulator, Variant of MAME with enhancements +#ifndef OPNMIDI_DISABLE_GX_EMULATOR +#include "chips/gx_opn2.h" +#endif + + static const uint8_t NoteChannels[6] = { 0, 1, 2, 4, 5, 6 }; static inline void getOpnChannel(uint32_t in_channel, @@ -36,43 +62,30 @@ static inline void getOpnChannel(uint32_t in_channel, out_ch = ch4 % 3; } -const opnInstMeta &OPN2::GetAdlMetaIns(size_t n) +void OPN2::cleanInstrumentBanks() { - return dynamic_metainstruments[n]; + dynamic_banks.clear(); } -size_t OPN2::GetAdlMetaNumber(size_t midiins) +static opnInstMeta2 makeEmptyInstrument() { - return midiins; + opnInstMeta2 ins; + memset(&ins, 0, sizeof(opnInstMeta2)); + ins.flags = opnInstMeta::Flag_NoSound; + return ins; } -static const opnInstData opn2_emptyInstrument = { - { - {{0, 0, 0, 0, 0, 0, 0}}, - {{0, 0, 0, 0, 0, 0, 0}}, - {{0, 0, 0, 0, 0, 0, 0}}, - {{0, 0, 0, 0, 0, 0, 0}} - }, - 0, 0, 0 -}; - -const opnInstData &OPN2::GetAdlIns(size_t insno) -{ - if(insno >= dynamic_instruments.size()) - return opn2_emptyInstrument; - return dynamic_instruments[insno]; -} +const opnInstMeta2 OPN2::emptyInstrument = makeEmptyInstrument(); OPN2::OPN2() : regLFO(0), - dynamic_percussion_offset(128), - DynamicInstrumentTag(0x8000u), - DynamicMetaInstrumentTag(0x4000000u), NumCards(1), - LogarithmicVolumes(false), m_musicMode(MODE_MIDI), m_volumeScale(VOLUME_Generic) -{} +{ + // Initialize blank instruments banks + cleanInstrumentBanks(); +} OPN2::~OPN2() { @@ -81,15 +94,7 @@ OPN2::~OPN2() void OPN2::PokeO(size_t card, uint8_t port, uint8_t index, uint8_t value) { - #ifdef OPNMIDI_USE_LEGACY_EMULATOR - if(port == 1) - cardsOP2[card]->write1(index, value); - else - cardsOP2[card]->write0(index, value); - #else - OPN2_WriteBuffered(cardsOP2[card], 0 + (port) * 2, index); - OPN2_WriteBuffered(cardsOP2[card], 1 + (port) * 2, value); - #endif + cardsOP2[card]->writeReg(port, index, value); } void OPN2::NoteOff(size_t c) @@ -113,7 +118,7 @@ void OPN2::NoteOn(unsigned c, double hertz) // Hertz range: 0..131071 if(hertz < 0 || hertz > 262143) // Avoid infinite loop return; - while(hertz >= 2047.5) + while((hertz >= 1023.75) && (x2 < 0x3800)) { hertz /= 2.0; // Calculate octave x2 += 0x800; @@ -134,8 +139,7 @@ void OPN2::Touch_Real(unsigned c, unsigned volume, uint8_t brightness) uint8_t port, cc; getOpnChannel(c, card, port, cc); - size_t i = ins[c]; - const opnInstData &adli = GetAdlIns(i); + const opnInstData &adli = ins[c]; uint8_t op_vol[4] = { @@ -185,13 +189,12 @@ void OPN2::Touch_Real(unsigned c, unsigned volume, uint8_t brightness) // 63 + chanvol * (instrvol / 63.0 - 1) } -void OPN2::Patch(uint16_t c, size_t i) +void OPN2::Patch(uint16_t c, const opnInstData &adli) { unsigned card; uint8_t port, cc; getOpnChannel(uint16_t(c), card, port, cc); - ins[c] = i; - const opnInstData &adli = GetAdlIns(i); + ins[c] = adli; #if 1 //Reg1-Op1, Reg1-Op2, Reg1-Op3, Reg1-Op4,.... for(uint8_t d = 0; d < 7; d++) { @@ -221,7 +224,7 @@ void OPN2::Pan(unsigned c, unsigned value) unsigned card; uint8_t port, cc; getOpnChannel(uint16_t(c), card, port, cc); - const opnInstData &adli = GetAdlIns(ins[c]); + const opnInstData &adli = ins[c]; uint8_t val = (value & 0xC0) | (adli.lfosens & 0x3F); regBD[c] = val; PokeO(card, port, 0xB4 + cc, val); @@ -248,7 +251,6 @@ void OPN2::ChangeVolumeRangesModel(OPNMIDI_VolumeModels volumeModel) break; case OPNMIDI_VolumeModel_CMF: - LogarithmicVolumes = true; m_volumeScale = OPN2::VOLUME_CMF; break; @@ -269,34 +271,51 @@ void OPN2::ChangeVolumeRangesModel(OPNMIDI_VolumeModels volumeModel) void OPN2::ClearChips() { for(size_t i = 0; i < cardsOP2.size(); i++) - delete cardsOP2[i]; + cardsOP2[i].reset(NULL); cardsOP2.clear(); } -void OPN2::Reset(unsigned long PCM_RATE) +void OPN2::Reset(int emulator, unsigned long PCM_RATE) { ClearChips(); ins.clear(); pit.clear(); regBD.clear(); - cardsOP2.resize(NumCards, NULL); + cardsOP2.resize(NumCards, AdlMIDI_SPtr()); - #ifndef OPNMIDI_USE_LEGACY_EMULATOR - OPN2_SetChipType(ym3438_type_asic); - #endif for(size_t i = 0; i < cardsOP2.size(); i++) { - #ifdef OPNMIDI_USE_LEGACY_EMULATOR - cardsOP2[i] = new OPNMIDI_Ym2612_Emu(); - cardsOP2[i]->set_rate(PCM_RATE, 7670454.0); - #else - cardsOP2[i] = new ym3438_t; - std::memset(cardsOP2[i], 0, sizeof(ym3438_t)); - OPN2_Reset(cardsOP2[i], (Bit32u)PCM_RATE, 7670454); - #endif + switch(emulator) + { + default: +#ifndef OPNMIDI_DISABLE_MAME_EMULATOR + case OPNMIDI_EMU_MAME: + cardsOP2[i].reset(new MameOPN2()); + break; +#endif +#ifndef OPNMIDI_DISABLE_NUKED_EMULATOR + case OPNMIDI_EMU_NUKED: + cardsOP2[i].reset(new NukedOPN2()); + break; +#endif +#ifndef OPNMIDI_DISABLE_GENS_EMULATOR + case OPNMIDI_EMU_GENS: + cardsOP2[i].reset(new GensOPN2()); + break; +#endif +#ifndef OPNMIDI_DISABLE_GX_EMULATOR + case OPNMIDI_EMU_GX: + cardsOP2[i].reset(new GXOPN2()); + break; +#endif + } + cardsOP2[i]->setRate((uint32_t)PCM_RATE, 7670454); + if(runAtPcmRate) + cardsOP2[i]->setRunningAtPcmRate(true); } + NumChannels = NumCards * 6; - ins.resize(NumChannels, 189); + ins.resize(NumChannels, emptyInstrument.opn[0]); pit.resize(NumChannels, 0); regBD.resize(NumChannels, 0); diff --git a/src/sound/opnmidi/opnmidi_private.hpp b/src/sound/opnmidi/opnmidi_private.hpp index 6e956d10f..ed10dcd10 100644 --- a/src/sound/opnmidi/opnmidi_private.hpp +++ b/src/sound/opnmidi/opnmidi_private.hpp @@ -63,6 +63,7 @@ typedef __int32 ssize_t; #include #include #include +#include #include // vector #include // deque #include // exp, log, ceil @@ -77,63 +78,88 @@ typedef __int32 ssize_t; #include #include -#ifdef _MSC_VER -#pragma warning(disable:4244) -#pragma warning(disable:4267) -#pragma warning(disable:4146) -#pragma warning(disable:4800) +/* + * Workaround for some compilers are has no those macros in their headers! + */ +#ifndef INT8_MIN +#define INT8_MIN (-0x7f - 1) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-0x7fff - 1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-0x7fffffff - 1) +#endif +#ifndef INT8_MAX +#define INT8_MAX 0x7f +#endif +#ifndef INT16_MAX +#define INT16_MAX 0x7fff +#endif +#ifndef INT32_MAX +#define INT32_MAX 0x7fffffff #endif - #include "fraction.hpp" -#ifdef OPNMIDI_USE_LEGACY_EMULATOR -#include "Ym2612_ChipEmu.h" -#else -#include "ym3438.h" -#endif +#include "chips/opn_chip_base.h" #include "opnbank.h" #include "opnmidi.h" +#include "opnmidi_ptr.hpp" +#include "opnmidi_bankmap.h" #define ADL_UNUSED(x) (void)x +#define OPN_PANNING_LEFT 0x80 +#define OPN_PANNING_RIGHT 0x40 +#define OPN_PANNING_BOTH 0xC0 + extern std::string OPN2MIDI_ErrorString; /* - Smart pointer for C heaps, created with malloc() call. - FAQ: Why not std::shared_ptr? Because of Android NDK now doesn't supports it + Sample conversions to various formats */ -template -class AdlMIDI_CPtr +template +inline Real opn2_cvtReal(int32_t x) { - PTR *m_p; -public: - AdlMIDI_CPtr() : m_p(NULL) {} - ~AdlMIDI_CPtr() - { - reset(NULL); - } - - void reset(PTR *p = NULL) - { - if(m_p) - free(m_p); - m_p = p; - } - - PTR *get() - { - return m_p; - } - PTR &operator*() - { - return *m_p; - } - PTR *operator->() - { - return m_p; - } -}; + return x * ((Real)1 / INT16_MAX); +} +inline int32_t opn2_cvtS16(int32_t x) +{ + x = (x < INT16_MIN) ? INT16_MIN : x; + x = (x > INT16_MAX) ? INT16_MAX : x; + return x; +} +inline int32_t opn2_cvtS8(int32_t x) +{ + return opn2_cvtS16(x) / 256; +} +inline int32_t opn2_cvtS24(int32_t x) +{ + return opn2_cvtS16(x) * 256; +} +inline int32_t opn2_cvtS32(int32_t x) +{ + return opn2_cvtS16(x) * 65536; +} +inline int32_t opn2_cvtU16(int32_t x) +{ + return opn2_cvtS16(x) - INT16_MIN; +} +inline int32_t opn2_cvtU8(int32_t x) +{ + return opn2_cvtS8(x) - INT8_MIN; +} +inline int32_t opn2_cvtU24(int32_t x) +{ + enum { int24_min = -(1 << 23) }; + return opn2_cvtS24(x) - int24_min; +} +inline int32_t opn2_cvtU32(int32_t x) +{ + // unsigned operation because overflow on signed integers is undefined + return (uint32_t)opn2_cvtS32(x) - (uint32_t)INT32_MIN; +} class OPNMIDIplay; class OPN2 @@ -142,39 +168,32 @@ public: friend class OPNMIDIplay; uint32_t NumChannels; char ____padding[4]; -#ifdef OPNMIDI_USE_LEGACY_EMULATOR - std::vector cardsOP2; -#else - std::vector cardsOP2; -#endif + std::vector > cardsOP2; private: - std::vector ins; // index to adl[], cached, needed by Touch() + std::vector ins; // patch data, cached, needed by Touch() std::vector pit; // value poked to B0, cached, needed by NoteOff)( std::vector regBD; uint8_t regLFO; - //! Meta information about every instrument - std::vector dynamic_metainstruments; - //! Raw instrument data ready to be sent to the chip - std::vector dynamic_instruments; - size_t dynamic_percussion_offset; - - typedef std::map BankMap; - BankMap dynamic_melodic_banks; - BankMap dynamic_percussion_banks; - const unsigned DynamicInstrumentTag /* = 0x8000u*/, - DynamicMetaInstrumentTag /* = 0x4000000u*/; - const opnInstMeta &GetAdlMetaIns(size_t n); - size_t GetAdlMetaNumber(size_t midiins); - const opnInstData &GetAdlIns(size_t insno); - + void cleanInstrumentBanks(); public: + struct Bank + { + opnInstMeta2 ins[128]; + }; + typedef BasicBankMap BankMap; + BankMap dynamic_banks; +public: + static const opnInstMeta2 emptyInstrument; + enum { PercussionTag = 1 << 15 }; + //! Total number of running concurrent emulated chips unsigned int NumCards; //! Carriers-only are scaled by default by volume level. This flag will tell to scale modulators too. bool ScaleModulators; - //! Required to play CMF files. Can be turned on by using of "CMF" volume model - bool LogarithmicVolumes; + //! Run emulator at PCM rate if that possible. Reduces sounding accuracy, but decreases CPU usage on lower rates. + bool runAtPcmRate; + char ___padding2[3]; enum MusicMode @@ -211,12 +230,12 @@ public: void NoteOn(unsigned c, double hertz); void Touch_Real(unsigned c, unsigned volume, uint8_t brightness = 127); - void Patch(uint16_t c, size_t i); + void Patch(uint16_t c, const opnInstData &adli); void Pan(unsigned c, unsigned value); void Silence(); void ChangeVolumeRangesModel(OPNMIDI_VolumeModels volumeModel); void ClearChips(); - void Reset(unsigned long PCM_RATE); + void Reset(int emulator, unsigned long PCM_RATE); }; @@ -402,7 +421,7 @@ public: bool eof() { if(fp) - return std::feof(fp); + return (std::feof(fp) != 0); else return mp_tell >= mp_size; } @@ -420,9 +439,15 @@ public: uint8_t bank_lsb, bank_msb; uint8_t patch; uint8_t volume, expression; - uint8_t panning, vibrato, sustain; + uint8_t panning, vibrato, aftertouch, sustain; + //! Per note Aftertouch values + uint8_t noteAftertouch[128]; + //! Is note aftertouch has any non-zero value + bool noteAfterTouchInUse; char ____padding[6]; - double bend, bendsense; + int bend; + double bendsense; + int bendsense_lsb, bendsense_msb; double vibpos, vibspeed, vibdepth; int64_t vibdelay; uint8_t lastlrpn, lastmrpn; @@ -431,53 +456,218 @@ public: bool is_xg_percussion; struct NoteInfo { + uint8_t note; + bool active; // Current pressure uint8_t vol; + // Note vibrato (a part of Note Aftertouch feature) + uint8_t vibrato; char ____padding[1]; // Tone selected on noteon: int16_t tone; - char ____padding2[4]; + char ____padding2[10]; // Patch selected on noteon; index to banks[AdlBank][] size_t midiins; - // Index to physical adlib data structure, adlins[] - size_t insmeta; - typedef std::map PhysMap; - typedef uint16_t Phys; + // Patch selected + const opnInstMeta2 *ains; + enum + { + MaxNumPhysChans = 2, + MaxNumPhysItemCount = MaxNumPhysChans, + }; + struct Phys + { + //! Destination chip channel + uint16_t chip_chan; + //! ins, inde to adl[] + opnInstData ains; + + void assign(const Phys &oth) + { + ains = oth.ains; + } + bool operator==(const Phys &oth) const + { + return (ains == oth.ains); + } + bool operator!=(const Phys &oth) const + { + return !operator==(oth); + } + }; // List of OPN2 channels it is currently occupying. - std::map phys; + Phys chip_channels[MaxNumPhysItemCount]; + //! Count of used channels. + unsigned chip_channels_count; + // + Phys *phys_find(unsigned chip_chan) + { + Phys *ph = NULL; + for(unsigned i = 0; i < chip_channels_count && !ph; ++i) + if(chip_channels[i].chip_chan == chip_chan) + ph = &chip_channels[i]; + return ph; + } + Phys *phys_find_or_create(unsigned chip_chan) + { + Phys *ph = phys_find(chip_chan); + if(!ph) { + if(chip_channels_count < MaxNumPhysItemCount) { + ph = &chip_channels[chip_channels_count++]; + ph->chip_chan = (uint16_t)chip_chan; + } + } + return ph; + } + Phys *phys_ensure_find_or_create(unsigned chip_chan) + { + Phys *ph = phys_find_or_create(chip_chan); + assert(ph); + return ph; + } + void phys_erase_at(const Phys *ph) + { + intptr_t pos = ph - chip_channels; + assert(pos < static_cast(chip_channels_count)); + for(intptr_t i = pos + 1; i < static_cast(chip_channels_count); ++i) + chip_channels[i - 1] = chip_channels[i]; + --chip_channels_count; + } + void phys_erase(unsigned chip_chan) + { + Phys *ph = phys_find(chip_chan); + if(ph) + phys_erase_at(ph); + } }; - typedef std::map activenotemap_t; - typedef activenotemap_t::iterator activenoteiterator; char ____padding2[5]; - activenotemap_t activenotes; + NoteInfo activenotes[128]; + + struct activenoteiterator + { + explicit activenoteiterator(NoteInfo *info = NULL) + : ptr(info) {} + activenoteiterator &operator++() + { + if(ptr->note == 127) + ptr = NULL; + else + for(++ptr; ptr && !ptr->active;) + ptr = (ptr->note == 127) ? NULL : (ptr + 1); + return *this; + } + activenoteiterator operator++(int) + { + activenoteiterator pos = *this; + ++*this; + return pos; + } + NoteInfo &operator*() const + { return *ptr; } + NoteInfo *operator->() const + { return ptr; } + bool operator==(activenoteiterator other) const + { return ptr == other.ptr; } + bool operator!=(activenoteiterator other) const + { return ptr != other.ptr; } + operator NoteInfo *() const + { return ptr; } + private: + NoteInfo *ptr; + }; + + activenoteiterator activenotes_begin() + { + activenoteiterator it(activenotes); + return (it->active) ? it : ++it; + } + + activenoteiterator activenotes_find(uint8_t note) + { + assert(note < 128); + return activenoteiterator( + activenotes[note].active ? &activenotes[note] : NULL); + } + + activenoteiterator activenotes_ensure_find(uint8_t note) + { + activenoteiterator it = activenotes_find(note); + assert(it); + return it; + } + + std::pair activenotes_insert(uint8_t note) + { + assert(note < 128); + NoteInfo &info = activenotes[note]; + bool inserted = !info.active; + if(inserted) info.active = true; + return std::pair(activenoteiterator(&info), inserted); + } + + void activenotes_erase(activenoteiterator pos) + { + if(pos) + pos->active = false; + } + + bool activenotes_empty() + { + return !activenotes_begin(); + } + + void activenotes_clear() + { + for(uint8_t i = 0; i < 128; ++i) { + activenotes[i].note = i; + activenotes[i].active = false; + } + } void reset() { - portamento = 0; + resetAllControllers(); + patch = 0; + vibpos = 0; bank_lsb = 0; bank_msb = 0; - patch = 0; - volume = 100; - expression = 127; - panning = 0xC0; - vibrato = 0; - sustain = 0; - bend = 0.0; - bendsense = 2 / 8192.0; - vibpos = 0; - vibspeed = 2 * 3.141592653 * 5.0; - vibdepth = 0.5 / 127; - vibdelay = 0; lastlrpn = 0; lastmrpn = 0; nrpn = false; - brightness = 127; is_xg_percussion = false; } - - MIDIchannel() - : activenotes() + void resetAllControllers() { + bend = 0; + bendsense_msb = 2; + bendsense_lsb = 0; + updateBendSensitivity(); + volume = 100; + expression = 127; + sustain = 0; + vibrato = 0; + aftertouch = 0; + std::memset(noteAftertouch, 0, 128); + noteAfterTouchInUse = false; + vibspeed = 2 * 3.141592653 * 5.0; + vibdepth = 0.5 / 127; + vibdelay = 0; + panning = OPN_PANNING_BOTH; + portamento = 0; + brightness = 127; + } + bool hasVibrato() + { + return (vibrato > 0) || (aftertouch > 0) || noteAfterTouchInUse; + } + void updateBendSensitivity() + { + int cent = bendsense_msb * 128 + bendsense_lsb; + bendsense = cent * (1.0 / (128 * 8192)); + } + MIDIchannel() + { + activenotes_clear(); reset(); } }; @@ -485,37 +675,71 @@ public: // Additional information about OPN channels struct OpnChannel { - // For collisions struct Location { uint16_t MidCh; uint8_t note; - bool operator==(const Location &b) const - { - return MidCh == b.MidCh && note == b.note; - } - bool operator< (const Location &b) const - { - return MidCh < b.MidCh || (MidCh == b.MidCh && note < b.note); - } + bool operator==(const Location &l) const + { return MidCh == l.MidCh && note == l.note; } + bool operator!=(const Location &l) const + { return !operator==(l); } char ____padding[1]; }; struct LocationData { + LocationData *prev, *next; + Location loc; bool sustained; - char ____padding[1]; + char ____padding[3]; MIDIchannel::NoteInfo::Phys ins; // a copy of that in phys[] - char ____padding2[4]; + //! Has fixed sustain, don't iterate "on" timeout + bool fixed_sustain; + //! Timeout until note will be allowed to be killed by channel manager while it is on int64_t kon_time_until_neglible; int64_t vibdelay; }; - typedef std::map users_t; - users_t users; // If the channel is keyoff'd int64_t koff_time_until_neglible; + + enum { users_max = 128 }; + LocationData *users_first, *users_free_cells; + LocationData users_cells[users_max]; + unsigned users_size; + + bool users_empty() const; + LocationData *users_find(Location loc); + LocationData *users_allocate(); + LocationData *users_find_or_create(Location loc); + LocationData *users_insert(const LocationData &x); + void users_erase(LocationData *user); + void users_clear(); + void users_assign(const LocationData *users, size_t count); + // For channel allocation: - OpnChannel(): users(), koff_time_until_neglible(0) { } + OpnChannel(): koff_time_until_neglible(0) + { + users_clear(); + } + + OpnChannel(const OpnChannel &oth): koff_time_until_neglible(oth.koff_time_until_neglible) + { + if(oth.users_first) + { + users_first = NULL; + users_assign(oth.users_first, oth.users_size); + } + else + users_clear(); + } + + OpnChannel &operator=(const OpnChannel &oth) + { + koff_time_until_neglible = oth.koff_time_until_neglible; + users_assign(oth.users_first, oth.users_size); + return *this; + } + void AddAge(int64_t ms); }; @@ -648,6 +872,8 @@ public: struct Setup { + int emulator; + bool runAtPcmRate; unsigned int OpnBank; unsigned int NumCards; unsigned int LogarithmicVolumes; @@ -655,6 +881,7 @@ public: //unsigned int SkipForward; bool loopingIsEnabled; int ScaleModulators; + bool fullRangeBrightnessCC74; double delay; double carry; @@ -688,6 +915,8 @@ private: std::map current_device; std::vector ch; + //! Counter of arpeggio processing + size_t m_arpeggioCounter; #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER std::vector > TrackData; @@ -760,7 +989,7 @@ public: #endif OPN2 opn; - int16_t outBuf[1024]; + int32_t outBuf[1024]; Setup m_setup; @@ -879,7 +1108,9 @@ private: Upd_Volume = 0x4, Upd_Pitch = 0x8, Upd_All = Upd_Pan + Upd_Volume + Upd_Pitch, - Upd_Off = 0x20 + Upd_Off = 0x20, + Upd_Mute = 0x40, + Upd_OffMute = Upd_Off + Upd_Mute }; void NoteUpdate(uint16_t MidCh, @@ -894,15 +1125,15 @@ private: // Determine how good a candidate this adlchannel // would be for playing a note from this instrument. - int64_t CalculateAdlChannelGoodness(size_t c, uint16_t ins, uint16_t /*MidCh*/) const; + int64_t CalculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t /*MidCh*/) const; // A new note will be played on this channel using this instrument. // Kill existing notes on this channel (or don't, if we do arpeggio) - void PrepareAdlChannelForNewNote(size_t c, size_t ins); + void PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins); void KillOrEvacuate( size_t from_channel, - OpnChannel::users_t::iterator j, + OpnChannel::LocationData *j, MIDIchannel::activenoteiterator i); void Panic(); void KillSustainingNotes(int32_t MidCh = -1, int32_t this_adlchn = -1); diff --git a/src/sound/opnmidi/opnmidi_ptr.hpp b/src/sound/opnmidi/opnmidi_ptr.hpp new file mode 100644 index 000000000..14e7591e1 --- /dev/null +++ b/src/sound/opnmidi/opnmidi_ptr.hpp @@ -0,0 +1,217 @@ +/* + * libOPNMIDI is a free MIDI to WAV conversion library with OPN2 (YM2612) emulation + * + * MIDI parser and player (Original code from ADLMIDI): Copyright (c) 2010-2014 Joel Yliluoma + * ADLMIDI Library API: Copyright (c) 2015-2018 Vitaly Novichkov + * + * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation: + * http://iki.fi/bisqwit/source/adlmidi.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef OPNMIDI_PTR_HPP_THING +#define OPNMIDI_PTR_HPP_THING + +#include // swap +#include +#include + +/* + Generic deleters for smart pointers + */ +template +struct ADLMIDI_DefaultDelete +{ + void operator()(T *x) { delete x; } +}; +template +struct ADLMIDI_DefaultArrayDelete +{ + void operator()(T *x) { delete[] x; } +}; +struct ADLMIDI_CDelete +{ + void operator()(void *x) { free(x); } +}; + +/* + Safe unique pointer for C++98, non-copyable but swappable. +*/ +template< class T, class Deleter = ADLMIDI_DefaultDelete > +class AdlMIDI_UPtr +{ + T *m_p; +public: + explicit AdlMIDI_UPtr(T *p) + : m_p(p) {} + ~AdlMIDI_UPtr() + { + reset(); + } + + void reset(T *p = NULL) + { + if(p != m_p) { + if(m_p) { + Deleter del; + del(m_p); + } + m_p = p; + } + } + + void swap(AdlMIDI_UPtr &other) + { + std::swap(m_p, other.m_p); + } + + T *get() const + { + return m_p; + } + T &operator*() const + { + return *m_p; + } + T *operator->() const + { + return m_p; + } + T &operator[](size_t index) const + { + return m_p[index]; + } +private: + AdlMIDI_UPtr(const AdlMIDI_UPtr &); + AdlMIDI_UPtr &operator=(const AdlMIDI_UPtr &); +}; + +template +void swap(AdlMIDI_UPtr &a, AdlMIDI_UPtr &b) +{ + a.swap(b); +} + +/** + Unique pointer for arrays. + */ +template +class AdlMIDI_UPtrArray : + public AdlMIDI_UPtr< T, ADLMIDI_DefaultArrayDelete > +{ +public: + explicit AdlMIDI_UPtrArray(T *p = NULL) + : AdlMIDI_UPtr< T, ADLMIDI_DefaultArrayDelete >(p) {} +}; + +/** + Unique pointer for C memory. + */ +template +class AdlMIDI_CPtr : + public AdlMIDI_UPtr< T, ADLMIDI_CDelete > +{ +public: + explicit AdlMIDI_CPtr(T *p = NULL) + : AdlMIDI_UPtr< T, ADLMIDI_CDelete >(p) {} +}; + +/* + Shared pointer with non-atomic counter + FAQ: Why not std::shared_ptr? Because of Android NDK now doesn't supports it +*/ +template< class T, class Deleter = ADLMIDI_DefaultDelete > +class AdlMIDI_SPtr +{ + T *m_p; + size_t *m_counter; +public: + explicit AdlMIDI_SPtr(T *p = NULL) + : m_p(p), m_counter(p ? new size_t(1) : NULL) {} + ~AdlMIDI_SPtr() + { + reset(NULL); + } + + AdlMIDI_SPtr(const AdlMIDI_SPtr &other) + : m_p(other.m_p), m_counter(other.m_counter) + { + if(m_counter) + ++*m_counter; + } + + AdlMIDI_SPtr &operator=(const AdlMIDI_SPtr &other) + { + if(this == &other) + return *this; + reset(); + m_p = other.m_p; + m_counter = other.m_counter; + if(m_counter) + ++*m_counter; + return *this; + } + + void reset(T *p = NULL) + { + if(p != m_p) { + if(m_p && --*m_counter == 0) { + Deleter del; + del(m_p); + if(!p) { + delete m_counter; + m_counter = NULL; + } + } + m_p = p; + if(p) { + if(!m_counter) + m_counter = new size_t; + *m_counter = 1; + } + } + } + + T *get() const + { + return m_p; + } + T &operator*() const + { + return *m_p; + } + T *operator->() const + { + return m_p; + } + T &operator[](size_t index) const + { + return m_p[index]; + } +}; + +/** + Shared pointer for arrays. + */ +template +class AdlMIDI_SPtrArray : + public AdlMIDI_SPtr< T, ADLMIDI_DefaultArrayDelete > +{ +public: + explicit AdlMIDI_SPtrArray(T *p = NULL) + : AdlMIDI_SPtr< T, ADLMIDI_DefaultArrayDelete >(p) {} +}; + +#endif //ADLMIDI_PTR_HPP_THING diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 1a034207c..b73520259 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2158,6 +2158,7 @@ ADVSNDMNU_OPLSYNTHESIS = "OPL Synthesis"; ADVSNDMNU_OPLNUMCHIPS = "Number of emulated OPL chips"; ADVSNDMNU_OPLFULLPAN = "Full MIDI stereo panning"; ADVSNDMNU_OPLCORES = "OPL Emulator Core"; +ADVSNDMNU_OPNCORES = "OPN2 Emulator Core"; ADVSNDMNU_GUSEMULATION = "GUS Emulation"; ADVSNDMNU_GUSCONFIG = "GUS config file"; ADVSNDMNU_MIDIVOICES = "MIDI voices"; @@ -2183,10 +2184,14 @@ ADVSNDMNU_FREEVERB = "Freeverb"; ADVSNDMNU_GLOBAL_FREEVERB = "Global Freeverb"; ADVSNDMNU_ADVRESAMPLING = "Advanced Resampling"; ADVSNDMNU_OPLBANK = "OPL Bank"; +ADVSNDMNU_ADLOPLCORES = "OPL Emulator Core"; +ADVSNDMNU_RUNPCMRATE = "Run emulator at PCM rate"; ADVSNDMNU_ADLNUMCHIPS = "Number of emulated OPL chips"; ADVSNDMNU_VLMODEL = "Volume model"; ADVSNDMNU_OPNNUMCHIPS = "Number of emulated OPN chips"; +// ADLMIDI's emulation cores + // ADLMIDI's volume models ADLVLMODEL_AUTO = "Auto (Use setup of bank)"; ADLVLMODEL_GENERIC = "Generic"; @@ -2373,9 +2378,13 @@ OPTVAL_512K = "512K"; OPTVAL_768K = "768K"; OPTVAL_1024K = "1024K"; OPTVAL_MAMEOPL2 = "MAME OPL2"; +OPTVAL_MAMEOPN2 = "MAME YM2612"; OPTVAL_DOSBOXOPL3 = "DOSBox OPL3"; OPTVAL_JAVAOPL3 = "Java OPL3"; OPTVAL_NUKEDOPL3 = "Nuked OPL3"; +OPTVAL_NUKEDOPL3174 = "Nuked OPL3 v1.7.4"; +OPTVAL_NUKEDOPN2 = "Nuked OPN2"; +OPTVAL_GENSOPN2 = "GENS YM2612"; OPTVAL_SOUNDSYSTEM = "Sound System"; OPTVAL_FOO_DUMB = "foo_dumb"; OPTVAL_ALIASING = "Aliasing"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 28f9e17d7..71043ea58 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1823,18 +1823,36 @@ OptionMenu ModReplayerOptions protected 5, "$ADLVLMODEL_WIN9X" } + OptionValue ADLOplCores + { + 0, "$OPTVAL_NUKEDOPL3" + 1, "$OPTVAL_NUKEDOPL3174" + 2, "$OPTVAL_DOSBOXOPL3" + } + + OptionValue OpnCores + { + 0, "$OPTVAL_MAMEOPN2" + 1, "$OPTVAL_NUKEDOPN2" + 2, "$OPTVAL_GENSOPN2" + } + OptionMenu ADLOptions protected { - Title "$ADVSNDMNU_ADLMIDI" - LabeledSubmenu "$ADVSNDMNU_OPLBANK", "adl_bank", "ADLBankMenu" - Slider "$ADVSNDMNU_ADLNUMCHIPS", "adl_chips_count", 1, 32, 1, 0 - Option "$ADVSNDMNU_VLMODEL", "adl_volume_model", "AdlVolumeModels" + Title "$ADVSNDMNU_ADLMIDI" + LabeledSubmenu "$ADVSNDMNU_OPLBANK", "adl_bank", "ADLBankMenu" + Option "$ADVSNDMNU_OPLCORES", "adl_emulator_id", "ADLOplCores" + Option "$ADVSNDMNU_RUNPCMRATE", "adl_run_at_pcm_rate", "OnOff" + Slider "$ADVSNDMNU_ADLNUMCHIPS", "adl_chips_count", 1, 32, 1, 0 + Option "$ADVSNDMNU_VLMODEL", "adl_volume_model", "AdlVolumeModels" } OptionMenu OPNOptions protected { - Title "$ADVSNDMNU_OPNMIDI" - Slider "$ADVSNDMNU_OPNNUMCHIPS", "opn_chips_count", 1, 32, 1, 0 + Title "$ADVSNDMNU_OPNMIDI" + Option "$ADVSNDMNU_OPNCORES", "opn_emulator_id", "OpnCores" + Option "$ADVSNDMNU_RUNPCMRATE", "opn_run_at_pcm_rate", "OnOff" + Slider "$ADVSNDMNU_OPNNUMCHIPS", "opn_chips_count", 1, 32, 1, 0 } /*======================================= diff --git a/wadsrc/static/xg.wopn b/wadsrc/static/xg.wopn index baeb34af2..ccb347977 100644 Binary files a/wadsrc/static/xg.wopn and b/wadsrc/static/xg.wopn differ