From ceec12056a7868c71ce8a3a8922af2abd8fad556 Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Wed, 20 Jun 2018 00:48:42 +0300 Subject: [PATCH] Upgrade libADLMIDI and libOPNMIDI Added ability to switch emulator and it's accuracy level ("enabling of 'run at PCM rate' reduces accuracy, and also reduces CPU usage") Added draft code for future external banks support (WOPL format for ADLMIDI and WOPN format for OPNMIDI) ADLMIDI 1.3.3 2018-06-19 * Fixed an inability to load another custom bank without of library re-initialization * Optimizing the MIDI banks management system for MultiBanks (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Fixed incorrect 4-op counter which is still catch 4-op instruments on 2-op banks * Fixed an incorrect processing of auto-flags * Fixed incorrect initial MIDI tempo when MIDI file doesn't includes the tempo event * Channel and Note Aftertouch features are now supported correctly! Aftertouch is the tremolo / vibrato, NOT A VOLUME! * Updated DosBox OPL3 emulator up to r4111 of official DosBox trunk (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * The automatical choosing of 4 operator channels count has been improved (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Added optional HQ resampler for Nuked OPL3 emulators which does usage of Zita-Resampler library (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) ADLMIDI 1.3.2 2018-04-24 * Added ability to disable MUS and XMI converters * Added ability to disable embedded MIDI sequencer to use library as RealTime synthesizer only or use any custom MIDI sequencer plugins. * Fixed blank instruments fallback in multi-bank support. When using non-zero bank, if instrument is blank, then, instrument will be taken from a root (I.e. zero bank). * Added support for real-time switching the emulator * Added support for CC-120 - "All sound off" on the MIDI channel * Changed logic of CC-74 Brightness to affect sound only between 0 and 64 like real XG synthesizers. Ability to turn on a full-ranged brightness (to use full 0...127 range) is kept. * Added support for different output sample formats (PCM8, PCM8U, PCM16, PCM16U, PCM32, PCM32U, Float32, and Float64) (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Reworked MIDI channels management to avoid any memory reallocations while music processing for a hard real time. (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) OPNMIDI 1.3.0 2018-06-19 * Optimizing the MIDI banks management system for MultiBanks (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Fixed incorrect initial MIDI tempo when MIDI file doesn't includes the tempo event * Fixed an incorrect processing of auto-flags * MAME YM2612 now results a more accurate sound as internal using of native sample rate makes more correct sound generation * Channel and Note Aftertouch features are now supported correctly! Aftertouch is the tremolo / vibrato, NOT A VOLUME! * Added optional HQ resampler for Nuked OPL3 emulators which does usage of Zita-Resampler library (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) OPNMIDI 1.2.0 2018-04-24 * Added ability to disable MUS and XMI converters * Added ability to disable embedded MIDI sequencer to use library as RealTime synthesizer only or use any custom MIDI sequencer plugins. * Fixed blank instruments fallback in multi-bank support. When using non-zero bank, if instrument is blank, then, instrument will be taken from a root (I.e. zero bank). * Added support for real-time switching the emulator * Added support for MAME YM2612 Emulator * Added support for CC-120 - "All sound off" on the MIDI channel * Changed logic of CC-74 Brightness to affect sound only between 0 and 64 like real XG synthesizers. Ability to turn on a full-ranged brightness (to use full 0...127 range) is kept. * Added support for different output sample formats (PCM8, PCM8U, PCM16, PCM16U, PCM32, PCM32U, Float32, and Float64) (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Reworked MIDI channels management to avoid any memory reallocations while music processing for a hard real time. (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) --- src/CMakeLists.txt | 21 +- src/sound/adlmidi/adldata.cpp | 10273 ++++++++-------- src/sound/adlmidi/adldata.hh | 58 +- src/sound/adlmidi/adlmidi.cpp | 468 +- src/sound/adlmidi/adlmidi.h | 184 +- src/sound/adlmidi/adlmidi.hpp | 21 +- src/sound/adlmidi/adlmidi_bankmap.h | 127 + src/sound/adlmidi/adlmidi_bankmap.tcc | 283 + src/sound/adlmidi/adlmidi_load.cpp | 432 +- src/sound/adlmidi/adlmidi_midiplay.cpp | 904 +- src/sound/adlmidi/adlmidi_opl3.cpp | 230 +- src/sound/adlmidi/adlmidi_private.cpp | 71 +- src/sound/adlmidi/adlmidi_private.hpp | 484 +- src/sound/adlmidi/adlmidi_ptr.hpp | 217 + src/sound/adlmidi/chips/dosbox/dbopl.cpp | 1618 +++ src/sound/adlmidi/chips/dosbox/dbopl.h | 284 + src/sound/adlmidi/chips/dosbox_opl3.cpp | 54 + src/sound/adlmidi/chips/dosbox_opl3.h | 23 + src/sound/adlmidi/chips/nuked/nukedopl3.c | 1391 +++ .../adlmidi/{ => chips/nuked}/nukedopl3.h | 46 +- .../nuked/nukedopl3_174.c} | 232 +- src/sound/adlmidi/chips/nuked/nukedopl3_174.h | 154 + src/sound/adlmidi/chips/nuked_opl3.cpp | 49 + src/sound/adlmidi/chips/nuked_opl3.h | 23 + src/sound/adlmidi/chips/nuked_opl3_v174.cpp | 49 + src/sound/adlmidi/chips/nuked_opl3_v174.h | 23 + src/sound/adlmidi/chips/opl_chip_base.h | 129 + src/sound/adlmidi/chips/opl_chip_base.tcc | 294 + src/sound/adlmidi/dbopl.cpp | 2045 --- src/sound/adlmidi/dbopl.h | 314 - src/sound/adlmidi/fraction.hpp | 9 + src/sound/adlmidi/wopl/wopl_file.c | 584 + src/sound/adlmidi/wopl/wopl_file.h | 290 + src/sound/i_musicinterns.h | 2 - .../mididevices/music_adlmidi_mididevice.cpp | 61 +- .../mididevices/music_opnmidi_mididevice.cpp | 60 +- .../gens/Ym2612_Emu.cpp} | 54 +- .../gens/Ym2612_Emu.h} | 22 +- src/sound/opnmidi/chips/gens_opn2.cpp | 52 + src/sound/opnmidi/chips/gens_opn2.h | 24 + src/sound/opnmidi/chips/mame/mame_ym2612fm.c | 2847 +++++ src/sound/opnmidi/chips/mame/mame_ym2612fm.h | 164 + src/sound/opnmidi/chips/mame/mamedef.h | 65 + src/sound/opnmidi/chips/mame_opn2.cpp | 54 + src/sound/opnmidi/chips/mame_opn2.h | 23 + src/sound/opnmidi/chips/nuked/ym3438.c | 1592 +++ src/sound/opnmidi/chips/nuked/ym3438.h | 246 + src/sound/opnmidi/chips/nuked_opn2.cpp | 49 + src/sound/opnmidi/chips/nuked_opn2.h | 25 + src/sound/opnmidi/chips/opn_chip_base.h | 110 + src/sound/opnmidi/chips/opn_chip_base.tcc | 268 + src/sound/opnmidi/fraction.hpp | 8 + src/sound/opnmidi/opnbank.h | 64 +- src/sound/opnmidi/opnmidi.cpp | 271 +- src/sound/opnmidi/opnmidi.h | 65 +- src/sound/opnmidi/opnmidi_bankmap.h | 127 + src/sound/opnmidi/opnmidi_bankmap.tcc | 283 + src/sound/opnmidi/opnmidi_load.cpp | 70 +- src/sound/opnmidi/opnmidi_midiplay.cpp | 643 +- src/sound/opnmidi/opnmidi_opn2.cpp | 133 +- src/sound/opnmidi/opnmidi_private.hpp | 463 +- src/sound/opnmidi/opnmidi_ptr.hpp | 217 + wadsrc/static/language.enu | 9 + wadsrc/static/menudef.txt | 30 +- wadsrc/static/xg.wopn | Bin 53214 -> 62080 bytes 65 files changed, 20498 insertions(+), 8987 deletions(-) create mode 100644 src/sound/adlmidi/adlmidi_bankmap.h create mode 100644 src/sound/adlmidi/adlmidi_bankmap.tcc create mode 100644 src/sound/adlmidi/adlmidi_ptr.hpp create mode 100644 src/sound/adlmidi/chips/dosbox/dbopl.cpp create mode 100644 src/sound/adlmidi/chips/dosbox/dbopl.h create mode 100644 src/sound/adlmidi/chips/dosbox_opl3.cpp create mode 100644 src/sound/adlmidi/chips/dosbox_opl3.h create mode 100644 src/sound/adlmidi/chips/nuked/nukedopl3.c rename src/sound/adlmidi/{ => chips/nuked}/nukedopl3.h (75%) rename src/sound/adlmidi/{nukedopl3.c => chips/nuked/nukedopl3_174.c} (83%) create mode 100644 src/sound/adlmidi/chips/nuked/nukedopl3_174.h create mode 100644 src/sound/adlmidi/chips/nuked_opl3.cpp create mode 100644 src/sound/adlmidi/chips/nuked_opl3.h create mode 100644 src/sound/adlmidi/chips/nuked_opl3_v174.cpp create mode 100644 src/sound/adlmidi/chips/nuked_opl3_v174.h create mode 100644 src/sound/adlmidi/chips/opl_chip_base.h create mode 100644 src/sound/adlmidi/chips/opl_chip_base.tcc delete mode 100644 src/sound/adlmidi/dbopl.cpp delete mode 100644 src/sound/adlmidi/dbopl.h create mode 100644 src/sound/adlmidi/wopl/wopl_file.c create mode 100644 src/sound/adlmidi/wopl/wopl_file.h rename src/sound/opnmidi/{Ym2612_ChipEmu.cpp => chips/gens/Ym2612_Emu.cpp} (95%) rename src/sound/opnmidi/{Ym2612_ChipEmu.h => chips/gens/Ym2612_Emu.h} (82%) create mode 100644 src/sound/opnmidi/chips/gens_opn2.cpp create mode 100644 src/sound/opnmidi/chips/gens_opn2.h create mode 100644 src/sound/opnmidi/chips/mame/mame_ym2612fm.c create mode 100644 src/sound/opnmidi/chips/mame/mame_ym2612fm.h create mode 100644 src/sound/opnmidi/chips/mame/mamedef.h create mode 100644 src/sound/opnmidi/chips/mame_opn2.cpp create mode 100644 src/sound/opnmidi/chips/mame_opn2.h create mode 100644 src/sound/opnmidi/chips/nuked/ym3438.c create mode 100644 src/sound/opnmidi/chips/nuked/ym3438.h create mode 100644 src/sound/opnmidi/chips/nuked_opn2.cpp create mode 100644 src/sound/opnmidi/chips/nuked_opn2.h create mode 100644 src/sound/opnmidi/chips/opn_chip_base.h create mode 100644 src/sound/opnmidi/chips/opn_chip_base.tcc create mode 100644 src/sound/opnmidi/opnmidi_bankmap.h create mode 100644 src/sound/opnmidi/opnmidi_bankmap.tcc create mode 100644 src/sound/opnmidi/opnmidi_ptr.hpp 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 baeb34af216e049c5f71bc92971a95f90e133a29..ccb34797763eb46530ea50425cc2f9c52947b069 100644 GIT binary patch literal 62080 zcmeHw3vgW5dES5D`?&jl;TYUV|&IOHK8CyuH$~^ z-d#M1dlzy<#ffuvI5>Nkd%yk9cmDIA|D5}u|9tT9z@hBgo!LW=kx2NbxO0>FN+Dk> zq_?am``3wm>D=BE_Wx&ox;>L#n{MDdR+_Z=YTssj<#26yq&P8I%P;;yFJ(948#^lb za`lugL3ZS? z=68$Zzx{_qAMWg>g znP7{XR?@BQG~SawI#MkZCz@2Jj}AOEq|ujY$Ff%x6oPyDqMWpf5z0M4w|mmNMyj)~Ly5Xa@DHLt-;OgN$!aJx=zBV>d8U|DW zj1=;tb8IkHbb5&54@_SW6dLHda{&sxrSlGWp)u7^)qRwCR!BmUa{f%IQnb@Ui`s`M z)D94pj-*VGOy@KS8jV{Z58f3*04bKCt2V0IXdUW}xN<_F_w-HqdCE{KpuI(c*9eHvz@m`qNuM}ZZU|xrqXTA)w*QhbO~b~A z0>)2pHFO~vKw*%sk~+nR9h^EjRnFIT7R%*{#a-tocWDisO~sYeUD}k2tEr2WbtNU^ zH>u`|h{ntG+`pD5d(yk7%EP76Vr?Fo3*W{`N*wm8Z<1$C&adtzLHdjf{0i<@Txg`| zM_h-P#*U6wE6`S3R)M#YqM;{Aeus_(P`pjOi6^P;Z90hpAEE>Pa!-1oSQ|zwpD7-$ zoywOgsL}9bsan~PH5&=lk+c3-Tf+Ng3WZ|r$~scDsGGV$Y(g;p6$AMgdNFj3-CtQ) ziTV{lmPaEkgV(5sgyhQ?$ODysnNS?{m<2$NvtB#}EA0rQQ=B4gFMFtqWHsWURUpIf z!G|R4thlwES+=9aV!;uD$2@+y0L@Fc+61hm!u3ta_NnlTQ3=hK!6sz{t z0Z3NNq+$v{YJGmUw2C&x!Y*(k()BpCFp!U!_5`g{8ivlA=J6h-C)!L~)_zT)S1Gh| zKqNPLx}z=>A_YHAtqcU54CX7Rs&#qLDy#wvUwy$yOF+i=rB**H1ns&Envc3}u)+d4 zbgo>j?3*f0=4;*ip|(e>n&7S>|+3LK_}WZ08T&onF6uQsm)GT2q&wvc5uwwSM1C*8fP zTAmuMOr#%qdFU@;5rzyoK__)#1+#3E#eyY@y-jJA z*S8NQ+*c^0Jkh3ICE0r-A^ZmtC>oY^`tS%n(vv=XrdTV~(09_^hX)R?^CMw9EB(-2Hs*I7|?eNSEnZ6 z2JFmFz_Kk;TAj8~x-;cbK1Uz!He8-psA~lV)fd2tp=r-h=N0-wPkL{ua;jK!fMCNY zbbJN$WF53@$Rn?#v0muhI#32>TSt?ZX#hs4G<=#t%n`ZZoe7dMV)P>Q`iFcBBmvjH}V4_<)B0#p%1$s)yXuE;3S6;g8^g~ z2rzr0Q<^>ynfANTTarUQ6w>DD01APIG*^P6-!}VB9b}PLXyKS3{%Jp4BwLVJmbn(W za}`sNbocIamHf_Hb>hK!3I`jzm3AkNrF>ozmBEzTO;LJ0hkQL2Mv z9mWhM$;OsDnwCcEOuN+tZP;{2RpaP8)2eHR+WxO_kPYb7a>>RP&9btkE0cmzilJF_ zx1`Y~!xzK=ElO8C`0&AXC3*_1y2t1{-lQV5X0;D@= zf~W0fbdYJOM*pD~?vn z)!bwa`fsPV{VOuD|Mnb3NQhkb(r$Q;0S_#$Kp4Z4tOLHv)c)CLOQ-XbjxZb0sDBjk zexAZgE|7eSLatyWfkHp(_x}!w-=P^8rN&gJ%sg5fV$l$7h6hMT&JTISN!S3xuM}wD z{2{M+msY>#`X;JV8Xe15&e_~u{|LU4XD|SpjLz>zZ$ZJFNO51lM}I}Gi_BB9$k;P6 zQ5-#4F52{<{z#_d54_L}q5Z}cP^qZ?E6lYZP-Aie|70PEO%Li1WjcP(i<^Y@t5;AN zLG`%k0XR%38eRd^zTPrv8!=F&J_^NJpQn?QX>WOsehqGl$8-)v6bjSW|6}$Y3k1E# z#(mT&8|&?I$@o5{1A;U`eSII7=yO2df5ieh!x81$b?^f29&=q~1td|>cdDh~qI27@>P%78BPA%~|D;dpCTYbnk9Z0k9lSWJY~W;a z#2E>uK;ClTfGNp?*O(-m)*mt@p}HjE%kz|NzwO+cIXM&=@G;Ld7FICX5JGV`99R*q zA3oIoRQew4J5!@$#YvkXht<)vY+~Cd{6dt(Si}zpOZEi4^kWj;Q6KqP-+{FstW`%( znsW@BwqeAs?V{FeKB0#we8mOdh}@sPB(~BK>C=}icZ-2cooq720La!bwcSt!%u%H4 zKF5WbjegU`hMNDaIBMAop9_$zYrnuQB0bWBpNW*Y zzgly$v;8D2yDDR5OXp2Z5D2cc+PH!<{J+^+0c=_hs}`nnv9DGvRtnWqv!jMi8^WEf zH%Qn=Y4@i{gu2jY6>%d))t4`brZdbsAjTbrW8ZP`+gVYF##MCw@g9Q_ooPqmgR(`K zV~y5A$A*%*LidGTOGbDdd*i7&1aZ(;0rr12-EWZvdn^h82`*E^j{{HLH_8 zLc)GZ`wx(Uin<)Ff89%7_ii*Xtl(LF-^jI|+?-z%fA*XdOu6dC3B~!9XJNOLMJr z_+%B{r>)9c#BL4?E0dpQQ?Bl~!HQIH8ihhsd8zeiM9dc0Sjcc1(Gm9 zL?vigP5i5@IujFEcX1L%r_GpQNS_A7wA{danuM;vGz!dj*cBu}2gLdb22f@T9IB*u zg<%&357okluXbFaaXHK;k|90vqS~16znI=z-15C;%n&RJ?f>=#O&g0vvG^x_w1=e3aa|mN+8?UhSg8HcqB)VQ*&{%b zhiTk3=$DF=U5vWu?Rge2K< zn7u6h3YwU?NZI6dA04BvRj>N!k14M}PgXNxF&kwdeY-|VPdf~xn7#?o8-5xhA%WsI zNL&4)--RoAP;&hSjed)DKnAj5*GRtRFhjtAUQ7LVfqp{csVFNVsiPW-kZfK-k_Rmi zXU_thuwD%F$a?XB)r(_`dNGq^)85k4lQyet@Cv>MV*8R$DDcN8{3l3KX_CyV^*WSS zr58RbT(%_H%q&xyEevC|df~#bPQ4O!8Y&u<5->^{QI}N^76CO7%Vu5!`9kJU@$8OM z_HDxk4Xq{MRnJhS^RkHbDOVf|t8jV9uUIbV4^5Et2QfWQcMo8;Uo51bhQpHHeegtM zhK}D3{tl5uy}^BKIg^448_;{LqU8&693a*5In!?ghc+)AoMc*$x@63M;7oEjx69juM5g5asX@+&~E9zkC65-P*2hXZGZ5vEYDU ze%wxK>+eZIo|G;R^Y{eyvMNrH*x^y>E}i|4zK_CFDo!$`A9lp)S2FFEZy&$<58>Op z{hCCtk?7R~`Yuy@3|?rR{djcah(T-QPJNe*PBTusWML4loBI;8Y;g}O(8O2{%AGA1 z?dD3esB4sEaaE;3no7zpuqj9ZcDEQYu>exRkZ~ei!xHN3J&WFKTc$>_^sx!!j?Ner zW5!M23M}87SGTsy9Sme`u2LAR<%jWHWpHGwQYhB;R%^q>^drYtF=u!Utxu_{e3y=< z6jgqca_*2s%PH&jNEkpGAiHYk@Cc!7XQvrRKkdP!Ts}kc>eh$`L#-PwZG^Icq)S^t z{>PbbzhiQ=nj0G_)=XP{ueC?z`XaT&D*}iOW#Y1;!c&^Qh=K4((05rq&WIg>o|uoT z4q+K)5gXPA5@ow@J|`ccV=D(;a+GqbhnU7@RTON#!_ z=L89J>|K{=J(^h2P~6(Ce+Nzu9_=)NAb5D$RRb4L9bxTNLLut7QfNGg6>D?mg?Vvq zxU{$AP!sdxq?}pyGP40)%dpP2i$<1Dvn#Lf;{A8Lqxfst4<pWJSbQXkFbGejDeAXqe zr%3x}Kkmw6jrv4f?jp&bjJsm=#8mJT0Lhox^BreaHqvBb@RitED#V`hY3R&a>;g>5 zWF)4$_mc0=#77w?rv^$6BPfuu&>a-Kp9rGgQhSJK1Ia7ljru?{Cb&N6iMec8Diq32 zmY&InsY-{nFty2CnA&9M)|%24YdMImZoyNkMlh(syO|DRwSXkUrGJXTEz%h_?v$&A(r|jP>VT3V5t9-hexfUdg))RI7$W8w z4BfAi^d#$m7>Ah{wicFs6~4Woc7)+di@u>Y*KybYqcx6&DJ+CU&jgxbzE%21JmGd(KEA)|7^WGeW;55Z2tVb zKmEZo{x$|O(P@E%4qfuQNlst$yKj@+Bgo897xR-N_V=5MFmSh+2+L^DWfnEBu4}&z zhg84pK0|?SX6~~Ajad# z*}Lv}13#_hw}XDo6$=G?SUzSH~vppVLBP`+9q6kH9d`E7#d_MO1qpYD?#} z7fnw|dJ-LQY^T0VI@AHOzj5m>Muazp0nPwtfHS}u;0$mEI0Kvk&H!hC zGw}W~u)B)5k@2Ga5-5JwTm?m-G8QcH8bXi~R?2kA-x?5>dlY{nAO~r{1S#ho)-KIE zw<^7|p$7i~7m=|4FH!i}au6OWCVgi}Qs`IBukk;e0nPwtfHS}u;0*lTX5c`6>eL7} zA2g{23yKSwVd1V9!|Di0-2*{vGZyHvmx3<8do%59ax?!g&H!hCGr$?(3~&ZG1DpZQ z0B3+Rz!~5Sa0WO7KSKssfI2dUI0dIevW?hf?J=U*s3s<`0|!OVG`m84Yzzf`jO9PE z_5xxLDzNNo^O%ABY(~PmEzXLS)7Diu$w0>0_5ti^s#Po1(V_#)YDl7*A_$5R!EIva zw24)h_UicrA#cbwP_fT} zZI`Z26bt)HBYFGK@ZHO4voI9w_#(B_pI(RbXX#EL^zVR$;v0lyH$HHJgo4dPVUom6 zNuqO-_$^7?Go-Fyk_;3J`LeShRM?C?XZt+uUqDuXJ8XO7v-DrC1b>~TwBPh~JWlii zi??T-IPS?n6DRE?na>H^W^#C}SlM6N@4yJro;7%=if)3mU*}E55nV>YwYzcU`^Q?% zlw|EFHfcIZ)3KF$7jZIAk`UV=!ia5#(rJPuBQrFQ*f|jSTV@j@_reJDeNl==Q+A@= zY=?;9C1g`1Bd+ypcAy=5caW3n&t@AnWO%~gZCtswNNd?nBIFBU$p-Evqkg^hp$*H_ zAw_%+i{`Hc^nXIKFs+C=+UC0H^W7%lGJOS>4SPG#JWjQtL9;rFIxw#~Uik%9omTZV z>im7_0rcYPS$i{Imt;Hk0|t$7=3gV!sVDABH4h3dcR~uptARln;+J2iZ0&$v7pV z`j1$35=g5QqHs{hHlF9{rfHO#2|}A^L2AB4)Z!!#kc=7*c-|(lo#mKfrU2QUPUao< zIPTku>a<63+n6umg*!lcdmu1Fy;@k;-y&ILi8NuTn_*BtK>QYnC*f^<(gcY=Nxk8) z9{&(aR0U6If2sN2M2y9f51aRXv7zX&F1miZaiu&W{4XX+bC3;7fb10RqVMES<|mr$ zJ>8Yru+B0C9~EC!#BmB(reHl?4|#uugejJO0U1j3!+B>PbRS#`I^j<~g5vAJ@FPg_ zaU3EyDK#w2NiK^BM` zNoyM*nm!Lie2S@k^L?Wj(EHJ4ocE0))CrO-1@f>Hh-z*=#r8RDK3xg~%4RP~9prTe z!ZJ^$cTFMBn_UAFt?j4UNpxJyw>lAjjD z<$9q3;y)l>XUdj8ZNJIV;%IT-@n19h4!REOJAc6X&ZBtvZEcsf?}Uf@Nl6-V;4Ufc zhCBEM$?hXwxJa@e#cSmH4C90i#K`66Q-W=k1t-S)gilFnvc%o%P5vdS66>w1%1zb}2ytR?@$8Q=_X1~>zp0nPwtfHS}u z;0*jM8F*~ZW6tL${VWCJzs(uo3~&ZG1Dt`sCk$W#lgFRf#-Es(8q)`D^`IVq5;5aX z+zaDRyeerY*bxTo%tW@H>abW&YY+z^A>SjiC$op5SRWS~`5rxiSFnI-rfOuZ^M1#l zEH~p%8c`oU^EqI^u%bS^XGwgU9bxb{5`WUYge2c#r&KI;!pkZ=Ht-CxXd=YE`0zXv z1$)$6KjB6HmvRply6;E)$x@Q6UP6+8#?mI=m-v&VBw5>B63>IuXRIan_Z)w+lqBnx zki;i_bm=DUeK#PEp$+vu{jTCqma0y62}$~;*Q~z75~V(9XMFt@hz_!Bdn=KYC3VV2Eo9rnm6z5kxJAu{7n5G=^zPui^bli$zoF8 zulSP%p(7{$n(-&@dGROGH`xifOGSO~_>;v={JzDX_~+tJ#N9mp@C`O-UwieGs}O%c3<9QXMZo1|D+BQTL9v+}qAQP}2?m;*^} z!%jxS%zr{p1%j7otOw`p;>c4g4T`wc%o4D_{*2cF>_8uliEV@(*JB!}`7xcB%>9<< zwHQkRME{-$lGtV`n3JU4L6S&a62B;b*oGtyU`!GXl8`0I8+2YZg1%EYDKzE}Y$80% z_&y|AKliJ4?^5qh67~e%?sn@lTS<@wnn~i`Nbc_n6-a_a56xc7noA=5p>P)<8=662 z5Bky|jl334SuNgG{u4-o6Q7&CR&ApX%qm+je7T`)tcfE?zwir8*?#)`Cp16*N%+uv zia(L8{3lzrdM1{ioBStBWk10=^V^uAW~Lw;81jWL(O|&vBv#U7!0;uo(|Ik;H1ve$ zKe^BOPj(@LL*Cicqf=!T^qscLG|^-DlfQ!Kt5m23eJ4o;6U06UwB9QhcEH6Tdx=aC z=iv`P%a@R3FH66`^Pen8qQdi^SV>gwNB$EYfAaI6|Afb%{2j=D!sAbxIlKJ-I0Kvk z&H!hCGr$?(3~&ZG1DpZQ0B3+Rz!~5Sa0WO7KOF-+{$z3d$!Vk<*)Y^SoL%L_WqLXO z$7qeXG(j~YC~#%q;GKFQy(Ux`$i}81%U77+k066O4mI(zWYI>@DnclQVnZ_%N~r3=yd`85?59J3Z4ql+cgUBn^3y6b0GB*W8!qC^f5Ok-;pgwn(_)_g zWF8syxBUE_#hmc`CyP1Z`A-&e!q4AX%!%FkJ3Rh`$Db_L6#fZkfHS}u;0$mEI0Kvk z&H!hCGr$?(3~&ZG1DpZQ0B7Lmm;oMtvN--^>C`3l^LL`=`8(c)=kFj4Mf@U5U9wdE zlP(W9YqgHOBq4U}6iYSG45iZqNk(SK7DWD* z*~GQ{#7O!*#h=uh7|f#RCF{$yGabF|HM)91TQ!etiEmK!Ux=5ahE zX^@>YV<;*+^~Q*)@8kJ9mIyrm$$id$(vvK(t9`oF{ zFs{NBj(grAnxPLdqtqN^8$gs>3}l=VQT<2wty>9t2P0ZIs3VEW^K{cRkIe+(=kM6G z5RX4uObU-bSzp0nPwtfHUy7je-9U D9kYz@ literal 53214 zcmeHQYj7Labw2yTbMb!ig#{n7C`z(Okd$PZQY7j{+j>wWEz7ZE1|nb*5s0NgP_jI2 zM7dHFOO#_PjvPwkx%p5);oYBQQk7u5CtEnoA*ZG697JWH9bQ%>hJ6~((T-z(HdpAyB} zB%dIF3>S0LGo?BxyQ!=FDW~*#n(#d3be^Yn;i)UqZ8|AF<#g;IXOFX|r(BiXlm?UR z-dD)Yrc1f0`ArqUL^|7kQnF=exOu{kf}_{3h!N_uzkXTFlH)Rkdy*q+;mm~z{7H6? ztA*UuQ8kmvW~vZG9!hm8F6nLJ-Ay*zMiRv)JN-5Fd77NGk(@jY_9Vw<)J%51PIU(8 z$U~EM`XcS?xFwkt^gTRJE{54x%0Od_r;A@6id@ zlM;WAQnKQqcPJ2Ua^cGMRoholopf<-J~suZ3>e9zXII!@tjP2bMITsR2fxL6Us>T&|Ec(nFovhbYjhft*NaAbsu24CJg1;{3Mr+W^Vt zp{oX}T4^2X4LQcSmc8_FN1IQ1ht39`5}E-*3Q0EdHIoO*mRG0FWDE0ixop0A-|9DV zZ!DqM>0fBDUvbkt+`Vk4f2FfNt&q-2XM2)I7r@A{`rPXKR=t;rfq1>Rdsn|l)<6LH zCe8V@!oFx<>`9)?oi3*5X4FD9*?kP;oKe@b4bh(D&h96D{B3%^bJEW}3uSxq5_g*h z=nWT_p*Qw&aY&Lb=4MZ)(K7jTCX-v+yi6pK4z?&Cw||&Ax|eT?FQC&TeD=4Ab1Odn zZKBud^`7LZ3;Bv5Mldp9=4kKFE6X&ce88vt2v?JfaUTkWWE*jZxI;b3iG|Y(`E+qO zo6pbJcAX!+Nn7ZAA}S@`q#cQ0ALdnkwbg!eB~kBveOCc_Y!7`->C^gj=O; zWV8F6)D2=oobqc7WEi~|y2kD=tgS@(3LstKP}9T`^$-_-b&*`C$E$>5OfLWejom-9 z04r?@BU6+@EjL}%Nun+2qD`;?vWp^UdaZz-dug45V4JCup7A z6m(WIkL#44XeaI3`WF&3Gq7=#CnveO!wwWYc|S_c3

IkuFTDWqHsltO9Fa1O8Bx zN5uDqW|_@^BVO@Pqo;uljuGb<9-+F5)O(oh3}B9Cwcr_wwNiR z?#5aA6qrXKHqc}ueB4uC-a`Pp%$oiZaN)@CT zdQt{?s{(>121vOk7{fH3o7dX;*<3NJ%Oq33BPS3-#)hMk@yC~V7a7mw`4|XdK*DdPYfI;;NI8p5O=g9ug_J8h4 z9?BJ_vqcjKHjF~YH$YFeLCYpx;x?M=h0bl$m2Dddzs>YyG&gm|6ha@1ZJkO0)~Gi& z8N%Hk+@knUa5U)@wo%{|136U8mN1acGa!RuLnfO@ZOu-*n?~uTJM?{sa8#fV(FdK6 z%JeP;gRF_iF=8-)zLhpz{Z6JNy)U%vb)dJzCp{>Hoy$HHki_nYk@TGO+zLpISExg2 zAl_v!T%>v+7Ydpn$?gLe3hCjZI{)A*g@cXVO$TC+Cp>QArHO>oNnv_2;c`)bd?F#e zNWyOjzX3^fkd(=o!6ez?d>!wLG%U&5ZK1-SM3(`aP_F`%&k*{p*o8pyyFT@nI_ zR-L0T)Wz(qnpek5Md-f~&QPQ;@+X%lL|o{an-0L~!>Gmd#O;Fpg(Mh8M|00VpF5K- znZgXBQNIy({}KhcF*$q>-S=2H@-_veF<0QLMBk(D!6;RxI(g>N8q^34(W1D3bmHQq zi!T90@k$vQy?D&c!^03c5!K1f&ZP?%4DK#}1YgND;e|~`=l8(4qF`dY3gf@U!vcHn_}0T10ID$$xU>7 z6$pBdf%_;^D$?62iTFMxWlorhs?8NZllCm~ipa;ONL@ zD4Y0u^oUlS(u_G0Oo6!Th%U*4nj|~=bxBB*1l8HHO4&vX=ibc8q0mteb6_Jr36l*j z5OHFb!P9Z3F2XKh7wbClC#^cc$j7wmJgQZPSIX5v-|;fF*9Wh{)Xa!l zG_$iq#C2Q~X*;5&9WKJAjU#HIITweE*=!-BPFF__nFfRH%`Xvm zn3B#<5D#^sPf7fC3fo>?DH=c8J6lE;Y~p`;ff zBm`wVk4pRw3c|PNolFuqe*5w;uOhBJYWFAlSk2;_(M=O=m_F2X2Qs{6Eh6qH84zF z3g*+qb^4Z3@Z@J#kOUnN@e_<0%odnbN$w0Lt`p~?V({4Ywrhx51ldF~AcsC?)8;#v zs=#}k!dPsAfesi;rRWY*&QxG&$#sW{wvRgKISRV(+(03GmmY-on8yr3r_lH>v#~*! zfS_3PWe*)Bp>IOwXDT)p)q#y2%W4zJqA>y_d6>>R#=Jt7QeBw0Z6JQf2|xchGmn>b zVn2ZDqzmyiwsB{;*wdG)-pEHtE52SzLvU%EjjN!awH2i8Rc zd4RRfm(c-d(q|TC(o-`z#%*psmrfoirl-r%HdJQ|4J17_zJn$@QFJ2a;d0V>L_l0G z!q*YUn6f=Fg9%T*j?%_LedJw4_4_U^5{*EFt2}F+i+{kH%-O>{rQ=gfPwM!O)z(RE zs&Z0k9nG~^LUqnAq>B(_6w|M4CiyHzkmP}*rz-XlV=>Qnja-VqOR2U|F8-@v&cBFQ zVlP}3%;L8E6MYyUX){L4L=VwfW)OY4UG#wy?JA`gWwlS|^Eq|ST;GNyDBCsG#PKB$ zJx-mQUiZ*nQko6uo6CLYNH(1r*gund)?^^X^oC9-dR$?L!sjSG%1 zQ3P!EBpJxy{+V>qWQKqNy_on0M?a#oi7+cdi7`8h0BKjA&$3?3K+HW0@WOiWiw%15 zk%Q^XjzhU;O9oLkcm>~u#ty`vlHkF%IJRWGx+wcx^Ex7{&UbVr&kc@vsh0MIQlk|1 zN{%6fTD_;{%@!e$h%yeVKAS?kt#T!QghfFQo!UBH$V?Q|Q&?A-m{}-fvc*GcaVnd9 zDn1O)10Hdep@!Y$D6Fp&Ml3s^$P8`)_FGDHV4DHqR? zxVbrGe}Ia-;;>J%P_@I}MM9I%1W&0ntB%jjWSNPqwf3moK%^ME#etJRUsRMNM9P*g zV`h88?{V5rlKc!;s4Q0eK+8KPV2 zX#^b15P*Xw4uZ%rG%v)wzdvtan&US!ix|Z1$Ck7T#ys=keLk5e) z)&s!|ecPm6IzYVRrhwjJZ~C|Z|Jv?VBov`8f>$t{E_}#b>Cwa~L~@RY9ZfVAd)mqQ zsr}%jF9x5OLQT#X2?N3aB$-Li=H|2JD!Y@UmSrzus9bzfqHhu3fvbN+`yjsh7CA;7 zBR$E-)RMU%teRcIcpSMGY^PG} z@lQm~Qzr6^$No54I080 zNMon|roRwHbfG|4vI$i5|CQhvr+K<%xBn)I-xjf$xNlmWHg6uy6bPPWzyBjuGen9k z->zJ7-{igtJz>HB1DK|pbs)L7b)P3hPtah8$8W!i)@jz41Do06Ah&_r0LM>NGjKqs z&KTB4lOz^aqR~5)aNTW^zYA|i3ATQbnxwm7Pn-~$#VlhYojaq#>s**ML?KGRdMpQn z7)@ox@5lO%h{|D!M^GFx)||Sjn~ghpHIti4PN*g*eZ*r@;=xaJCYZBFyut_B4<^Wq zQ8}zFh+HTzF-&YDzWXr7ytW`*Y2Gv0;y6j1Lurm8Fokei;A@bJ#o5NPSVEZ3Cih>M zJ#E;|L;j1@#?c~147iP93OR>wM4d!!Ki6WrO|f&V@05f8EZ&_wrlLPHNmsvy{O7#Q z3}n7t2MHXx>UENsyykV@Chi691!kzT>C%kx{aO%)`S!Bz+iL}Ud)fX4*b~=_&T}N3 z6V5?TvgvUwpw|dc6=pZ}ixA-l%ruK^Ju{{k5v_RW0N(*ga>dL9#^X};u61wVr!{@e z@3m7T;PZH0xhM4c-cuhT+f2YP#Hm}8h1#T#txF3i6GwWW)~$8=BWBj|v0bNTc_ZKG5r zS;dLX0}w7|vty#eMQlC|M7YeFxG+DXnleJIyCo1S1envQgu}4cq_E5YR`~y&&>zoM zf6sbjF<>!ZF<>!ZF<>!ZG4SIvz$OUD*f5(M;0LzHiFYYs1Pb{Wl0Q)NEVC>4ClM4_ zfJ0=s9FN@(r^|4T@R)-9SS6<47G=f8W&J7`uYw?^R8$MMeFo7h6t%)Py2eC&McGPAFCIokO;2$j%vXgX?oW8fn zc9DECW=n|B%9y|0WD&oHAkC{l?7lY{h-VduHs8@&XFQiN^UJrOIuVTw&RgN6+&ZkF zc5UGdX@Y3w@q!jJUy~)MRdC}VT+q8VKSF(UH|S-)=d$jCF8gK7Q-)dGegqlNSmT*9 zOLf{cL_W_li~NwFgppL|Yf%C|mL{PHK}>rF*^1=8_auqr(aUSpUsTqX41y4 z`GGFl$xZs(ev4Y^?{8oxe4g(50>2F`6j-+Qu!!FX61wY&vLZ=%MG~(ri4*D)-~xz( zW;5x$xgeC;iJ0GESL^4HfpV8HuXvvR@S6V%v|#^=r|rq|yqIxfIwwXW$E%#Il4OMw z?q%*}EX~Yi3nRG^6Go5>u?2G+bQ3?ONt)vD4khL|P`%3Yd98J}&SFi*Oq#ac)T_6S zu_SxBy*jb=P}((+c<3G(g3y=Qn%91;ea~Q$Uy~xQ$xd{D&CnG$?ZpgBiP{IiuX3FQ z>u9;fejA}B-cfF1)FoNIX?@XEpI9tb-a)JY9k?7PFkFj2vIWbiNXDrWD^NUQUm&Ylz?|x{o!!{}Lm#{E-%P0Q=vObn2ew_9=ZhAb3 zPif(xam=mJJSMe45Lc^?WE*9zQ?8C%yuzx}Y{NoAkuQQ1^}Ml}FH5o)@mRkS4E#-{ z0(L@ZX`ymO8J2;mi@;KY3^nDDE(sym5R!y-VqFztKSR8i_iCx~S(b5VLJ74FUA_vuzSOY(V(#N)b0dIyAg ztS1QVs8**&k`)kU?U7w~I&BhTKD-+_+^u0Gpw3aujgcI&Y9CT`dnqW(7{gpFpAC}K z!=NF6c&i}IPir92r!|o12g*anNUnZt7-MnW$gmbRJfhYI8EgRZGaTY<`_re>^L1kX z`}+pB>89Xk`PU`>EctX(&`&o4?q4Yn=y*aTJ(V{1K@Y>Vpi|!XBPjmHAAAH!7B5Ac zZjet227_4B(OpnPFH7YN1&~(r+948cz{3X!D6_%q2gq>>x}%#bS9(zQh+3GggMkoe zEr??Ug#Tr>z{=vNB^KH(8teX^A^g7Lc2$=TiI=^8gvps)czRBYf-*_!V2}>tbgqEd zovT3jkMIa!){om`Kp&#IaeK`LZ3ObL8Hh~}{%ek3BM>N?u_UWOSmyu!1*F+(Jk|br zRK&bO_W9s}>r~=_46n~oxzfD?=H%1^8L9C@xI2>0hAmScz4^y`E8RHLEnJvh-7xa94wkV2xd%luy@ABO$=N0@^@=v<7{1cO`4?Lr(Wqtfq z@=v&_B>r2Al;BVZg{F6qK zY-=FNpRvc*8iDjS0QnaGtx8^jNmc>+^?S-cX(UOiz9f1Rv%bR~RC!R>y5x~{R^>R$ zgz>qtG;@~1E%rB&Iug20pRZ)XaNps+gX&oMCqJ3|lWOa*1;OOVy0#%b{{+c`EdQiM z&p+|6&Oh1CZ@*9ZCsj$xda_=Y_pzLuX1kdrLQn`=`6uOc8YHo-q>fnmCu^QewDM1^ z{1ay8to)Pp#-7N^KdI%!%0H>)#L7RZ<;42LV!&d+V!&d+V!&d+V!&d+V!&d+V!&d+ zV!&d+V!&d+Vqh%;R{n`u{z<+4Pue%&d1QrR*zqo+1aOSW_KS*-J>rc0PuSC!+U6LI z_CG0u;82NGAZ{JR1CR&VUhelL|3u&TWc{M|iX!YC!pb+E)?_aw7I(6%VC&b}RXA{= zoC#COKheHr@TdD>_WdB+AW;fOQHbIz+H;B&4f)@wR7cx_W&N`13Yw85q1Nv)LoRGwDmx2{ZT1_Mgl_hzOaKuto5)&{ci5-&Qgg++9 z59p#z@q4BTl6ZYPh_28TNYcOZt48k<4J5%Xi%b%>0&jG?{+Xd9IP8;2;>6>iDJ}&` zu+c-kS4U$>05Vt)0?(i~0MT~XFxy(A0{tHHPaw(m%GZs{O?&8lRb}%BU#ut_YvRy5 zL?2)~9$WjL{6zLYX|($Z_W9n!3^g+aDVp>IuVPyj#TDC#4fhpK45n5)7Sr1Q;GeW&F`n(tA(@n1pqRU*)YzB5Xr8i;WcXt_VG?SQo)=ztoC`S1sz zt_G55z1Z6SWK9x_wf~8p#A5A#@*cJ>vGzZ)_CK-qKQVS8txqimECwtFECwtFECwtF zECwtFECwtFECwtFECwtFECwtF{;x7%<)75%pPa!VLW7gtQ>jg6t)A?{f0X8s!_L{1 z5DHu=I90MzAa#U+Y_AK_wL$xS2>YdAb8a`=EL!pFMSvCeEB{2#KG_L)v)6_pWS=PH z;IOg15{u?2ND3FgIg*eoc#3ci=}9Cf{P^eZG?wJS29n@(B%}nG)ua5m|6%MBFv*UB zE=4BU@lMZmPsZevSahCr!VM&OmwWfV?0?c&lBW8S=-c(P?2{k! z{GG;kIvapQ_{e?P|D>@b8yZN`%C}niC)W8p*7-XIM%y}nrKCT>-?QsPHOv(b^eZZ{!Xo)Sf5x7SPWPUSPWPUSPWPUSPWPUSPWPU zSPWPUSPWPUSPWPU`~(=V@=t2>PjHlZdVap%{wMX$-;t4qa+7Yp2M`?TKrIxqv-8mH zI9uIzkv#G}Z4(s+f*m&Q%l;>gvp!No6reCkq~)Jz`=7KaY#$dSr39RWV<*_=7(b2t zlL599OBk6WBvf`{Y4dx3sVWJci0?__Foooyys8$H#_0j!-P9LNX#1ZC&&b?8n$x!% z@eBI?C!eNI->36;*c0*fL|Ks}ydsJB9x+LrXz2hKxG(u9Iw!_#=td)6Jv+M=#G_tV&$J$`6o3!2S;6C&m`#$A2I~bQY`4gu2Q7!#Db%9w5wqn zW=3fwx1S|vn!M_OSm*B$GBMdprZroaSm*EPTbH<_n{|e;X`9H2Y#1#}KQWV=FXgj_ z>eeq}@2#MV+?CtB6twm~vGzY%uPjqtBs62Qy2VNdL}ItsbG>p!$fMTXt%+hTU6?l3 zHX{&+<4OfY+#~M61Yst9CR<$p`zzO0{>cg#m3LPDNrefkv>31$uo$oyuo$oyuo$oy Kuo$Ri;J*M=0{DOc